Python之反射

1、引子:isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

class Foo:
    pass

obj = Foo()
print(isinstance(obj,Foo))

issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo:
    pass

class Bar(Foo):
    pass

print(issubclass(Bar,Foo))


2、什么是反射

面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

对象的反射

class People:
    coutury='China'
    def __init__(self,name):
        self.name=name

    def walk(self):
        print('%s is walking'%self.name)

p1=People('hjc')
print(p1)
# print(People.coutury)
# print(p1.coutury)
# print(People.__dict__)


# hasattr 判断这个对象有没有响应的属性
# print('name' in p1.__dict__) # 相当下面
# print(hasattr(p1,'name'))  # 判断这个 name 属性在不在这个对象的 dict 里面
# print(hasattr(p1,'coutury'))
# print(hasattr(p1,'__init__'))

# getattr 调用对象中存在的属性
res=getattr(p1,'coutury') # 相当于 res=p1.coutury=China
print(res)   # 对象.属性,这里 coutury 是对象的数据属性

res1=getattr(People,'walk')  # 相当于 res1=People.walk=一个函数的内存地址
print(res1)  # 类名.属性,这里 walk 是类的函数

res2=getattr(p1,'walk')  # 相当于 res2=p1.walk=一个绑定方法的内存地址
print(res2)  # 对象.属性,这里 walk 是对象的绑定方法

res2()  # 相当于 res2()=p1.walk(p1) 绑定方法自动把对象传值
res1(p1) # 相当于 res1()=People.walk(p1) 函数手动把对象传值

res3=getattr(p1,'xxxxx','这个属性不存在')  # 如果属性不存在,可以给个提示
print(res3)

# 用法,可以用来判断属性存不存在,存在就执行,不存在就过
if hasattr(p1,'walk'):
    func=getattr(p1,'walk')
    func()
print('-------')


# setattr
p1.sex='male'
print(p1.sex)
setattr(p1,'age',18)  # 通过 setattr 可以对对象进行设置属性,格式:对象,'属性','值'
print(p1.__dict__) # 查看有没有到 对象里面去
print(p1.age)
print(getattr(p1,'age')) # 取 setattr 设置的值


# delattr
print(p1.__dict__)
del p1.sex   # 删除对象属性的第一种方法
print(p1.__dict__)
delattr(p1,'age')  # 删除对象属性的第二种方法
print(p1.__dict__)



模块的反射

import sys

class foo:
    pass

def s1():
    pass

def s2():
    pass

this_module=sys.modules[__name__]
print(this_module)   # 一个模块的对象
  
print(hasattr(this_module,'s1'))  # 查看方式跟对象的反射一样
print(getattr(this_module,'s2'))  # 只不过对象是模块
print(getattr(this_module,'foo'))
print(this_module.foo)
print(this_module.s1)


类的反射

class Foo:
    f = 123
    @classmethod
    def class_method_dome(cls):
        print('class_method_dome')

    @staticmethod
    def static_method_dome():
        print('static_method_dome')

print(hasattr(Foo,'class_method_dome'))
method = getattr(Foo,'class_method_dome')
method()
print('------------')
print(hasattr(Foo,'static_method_dome'))
method1 = getattr(Foo,'static_method_dome')
method1()


3、为什么用反射?

实现可插拔机制

有俩程序员,一个lili,一个是egon,lili在写程序的时候需要用到egon所写的类,但是egon去跟女朋友度蜜月去了,还没有完成他写的类,lili想到了反射,使用了反射机制lili可以继续完成自己的代码,等egon度蜜月回来后再继续完成类的定义并且去实现lili想要的功能。

总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

ftpclient.py

class FtpClient:
    'ftp客户端,但是还么有实现具体的功能'
    def __init__(self,addr):
        print('正在连接服务器[%s]' %addr)
        self.addr=addr


ftpserver.py

from ftpclient import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
    func_get=getattr(f1,'get')
    func_get()
else:
    print('---->不存在此方法')
    print('处理其他的逻辑')
.
原文地址:https://www.cnblogs.com/tootooman/p/9225303.html