python学习笔记之反射
反射
什么叫反射?
给定一个对象,返回该对象的所有属性和函数列表,或给定对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例。
dir函数就是反射的实现,如下:
['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']
给定int
对象,返回了此对象的所有属性和函数列表。
再来看一个特殊方法__dict__
,先定义一个类,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Grok: X = 1 Y = 2 Z = 3 def __init__(self,x,y,z): self.x = x self.y = y self.z = z
def method(self): print('call method') grok = Grok(1,2,3)
|
{'x': 1, 'y': 2, 'z': 3}
类所有的实例属性都能通过__dict__
输出,这种对定了一个实例对象,返回了该实例对象的属性,这也是反射的体现。
__main__.Grok
通过__class__
能够返回一个实例对象是由哪个类产生的
['__sizeof__',
'__ne__',
'__repr__',
'__class__',
'method',
'__new__',
'__eq__',
'__init__',
'x',
'__weakref__',
'__format__',
'__gt__',
'__lt__',
'Y',
'Z',
'__subclasshook__',
'z',
'X',
'__delattr__',
'__reduce__',
'__getattribute__',
'__dict__',
'__doc__',
'__module__',
'__dir__',
'__hash__',
'__reduce_ex__',
'__le__',
'__str__',
'__ge__',
'__setattr__',
'y']
getattr用于返回一个对象属性,或者方法
1
<bound method Grok.method of <__main__.Grok object at 0x7f570c405358>>
<bound method Grok.method of <__main__.Grok object at 0x7f570c405358>>
上边两种调用都是返回method函数对象,也可以直接调用,如下:
1
| getattr(grok,'method')()
|
call method
call method
设置一个对象的属性
123
删除一个对象的属性
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-42-6ec68937908b> in <module>()
----> 1 getattr(grok,'a')
AttributeError: 'Grok' object has no attribute 'a'
__getattr__
__setattr__
__delattr__
上边的getattr
,setattr
,delattr
三个函数是分别对应__getattr__
,__setattr__
,__delattr__
这三个特殊方法。
先来看一个例子,如下:
1 2 3 4 5 6 7
| class Grok1: def __init__(self): self.__dict = {'x':1,'y':2} def __getattr__(self,name): print('call __getattr__') return self.__dict.get(name)
|
call __getattr__
1
从上边的例子可知,当访问实例对象的一个属性时,这里直接调用了__getattr__
方法,如果此属性在构建函数中存在呢?如下:
1 2 3 4 5 6 7 8
| class Grok2: def __init__(self): self.__dict = {'x':1,'y':2} self.x = 10 def __getattr__(self,name): print('call __getattr__') return self.__dict.get(name)
|
10
当访问实例对象的属性时,此属性在构建函数时已定义,那直接返回,如果没有,则去__getattr__
查找,如果这个函数中也没有,查找才结束。
再来看一个getattr
的使用例子,如下:
1 2 3 4 5 6 7 8 9 10 11 12
| class Grok3: def method_a(self): print('call method_a') def method_b(self): print('call method_b') def method_default(self): print('call method_default') def __getattr__(self,name): return self.method_default
|
1
| getattr(grok3,'method_a')()
|
call method_a
1
| getattr(grok3,'method_b')()
|
call method_b
1
| getattr(grok3,'method_c')()
|
call method_default
call method_default
上边这个例子说明当我们调用一个不存在的方法时,比如这里的method_c
,如果类中定义了__getattr__
方法,那么会去调用此函数定义的操作,这就在python中实现了一个默认操作,避免当用户调用一个不存在的方法或属性时解释器会抛出错误,而__getattr__
函数后,可以给用户一些提示信息。