一、反射机制 *
反射可以理解为
- 通过字符串的形式,动态导入模块;
- 利用字符串的形式,在对象(模块)中操作(查找/获取/删除/添加)成员,是一种基于字符串的事件驱动!
反射机制的内置函数
# hasattr(object,attr)
# 输入两个参数(对象,字符串类型(方法或属性)),判断一个对象里是否有某个属性或方法,返回布尔值,有为True,否则False
class Foo:
def f1(self):
pass
obj = Foo()
print(hasattr(obj,"f1"))
# 运行结果:True # getattr(object,attr[,default])
# 获取对象的属性或方法,可设置输出默认值,
# 如果获取方法,返回的是内存地址,如果需要运行,后面添加一对括号
class Foo:
def f1(self):
print("获取了f1方法")
obj = Foo()
ret = getattr(obj,"f1")
ret()
print(ret)
# 运行结果:获取了f1方法 \
# <bound method Foo.f1 of <__main__.Foo object at 0x0000024FE505E9B0>> # setattr(object,attr,values)
# 动态的给对象的属性赋值(内存地址),若属性不存在,则先创建再赋值
class Foo:
def __init__(self,a1):
self.a1 = a1
obj = Foo(1)
print(getattr(obj,"a1"))
#运行结果:1
setattr(obj,"a1",2) # 将对象中的属性重新赋值
print(getattr(obj,"a1"))
#运行结果:2
setattr(obj,"a2",3) #在对象中创建一个新的属性a2并赋值
print(getattr(obj,"a2"))
#运行结果:3 # delattr(object,attr,values)
# 动态的删除对象的属性(内存地址)
class Foo:
def __init__(self,a1):
self.a1=a1
obj = Foo(1)
print(getattr(obj,"a1"))
# 运行结果: 1
setattr(obj,"a2",2)
print(getattr(obj,"a2"))
# 运行结果: 2
delattr(obj,"a2")
print(getattr(obj,"a2")) #删除对象中的属性
#运行结果:AttributeError: 'Foo' object has no attribute 'a2'
反射的内置函数
二、如何正确的判断方法与函数?
目前我们印象中的方法就是封装在类内部的函数,实际上这样说不严谨;
# 如何判断方法与函数
# tpye
# 判断类型
class Foo:
def f1(self):
pass
obj = Foo()
print(obj,type(obj.f1)) # 当我们用对象调用类中的方法时,我们通过type查看到的是方法
# 运行结果:<__main__.Foo object at 0x0000028E0F10E898> <class 'method'>
print(Foo,type(Foo.f1)) # 当我们用类调用类中的方法时,我们通过type查看到的是函数
# 运行结果:<class '__main__.Foo'> <class 'function'>
# 总结:封装在类中的函数通过对象调用时是真正的方法。
三、callattr()、issubclass()、isinstance、type()的使用
callattr()方法是用来判断传入的参数是否可以被调用
callable
判断输入的参数是否可以被调用
class Foo:
def f1(self):
pass
def __call__(self, *args, **kwargs):
pass
def func():
pass
obj = Foo()
print(callable(Foo)) # 类是可以被调用的类型
# 运行结果: True
print(callable(obj.f1)) # 方法是可以被调用的类型
# 运行结果: True
print(callable(func)) #函数是可以被调用的类型
# 运行结果: True
print(callable(obj)) #实例化的对象是可以被调用的类型,注:类的内部要有__call__方法
# 运行结果: True
issubclass()方法是用判断传入的两个参数,前一个参数是否是后一个参数的派生类
# issubclass
# 判断传入的两个参数,前一个参数是否是后一个参数的子类
class Base:
pass
class Foo(Base):
pass
print(issubclass(Foo,Base))
# 运行结果: True
isinstance()方法是判断传入两个参数,第一个传入的参数(对象),是否是第二个参数(类)的实例
# isinstance
# 判断传入两个参数,第一个传入的参数(对象),是否是第二个参数(类)的实例
class Base:
def f1(self):
pass
def f2(self):
pass
class Foo(Base):
def f1(self):
pass
class Last:
pass
obj = Foo()
print(isinstance(obj,Last))
#运行结果:False
print(isinstance(obj,Foo)) # obj是Foo类的一个实例化对象
#运行结果:True
print(isinstance(obj,Base))# obj也可以是Foo基类的一个实例化对象
#运行结果:True
# 总结:isinstance可以判断对象是否是类或类的基类中的实例
type()
# type
# 判断传入的参数(对象)是哪个类的实例化对象
class Base:
pass
class Foo(Base):
pass
obj = Foo()
print(obj,type(obj)) # 获取当前对象是由哪个类创建
# 运行结果: <__main__.Foo object at 0x000001567FC9E8D0> <class '__main__.Foo'>