python反射

python学习笔记之反射

反射

什么叫反射?

给定一个对象,返回该对象的所有属性和函数列表,或给定对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例。

dir函数就是反射的实现,如下:

1
dir(int)
['__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)
1
grok.__dict__
{'x': 1, 'y': 2, 'z': 3}

类所有的实例属性都能通过__dict__输出,这种对定了一个实例对象,返回了该实例对象的属性,这也是反射的体现。

1
grok.__class__
__main__.Grok

通过__class__能够返回一个实例对象是由哪个类产生的

1
grok.__dir__()   #这也是反射的体现
['__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

getattr用于返回一个对象属性,或者方法

1
getattr(grok,'X')   #返回grok实例的类的X变量的值
1
1
getattr(grok,'method')
<bound method Grok.method of <__main__.Grok object at 0x7f570c405358>>
1
grok.method
<bound method Grok.method of <__main__.Grok object at 0x7f570c405358>>

上边两种调用都是返回method函数对象,也可以直接调用,如下:

1
getattr(grok,'method')()
call method
1
grok.method()
call method
  • setattr

设置一个对象的属性

1
setattr(grok,'a',123)
1
getattr(grok,'a')
123
  • delattr

删除一个对象的属性

1
delattr(grok,'a')
1
getattr(grok,'a')
---------------------------------------------------------------------------

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__

上边的getattrsetattrdelattr三个函数是分别对应__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)
1
grok1 = Grok1()
1
grok1.x
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)
1
grok2 = Grok2()
1
grok2.x
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
grok3 = Grok3()
1
getattr(grok3,'method_a')()
call method_a
1
getattr(grok3,'method_b')()
call method_b
1
getattr(grok3,'method_c')()
call method_default
1
grok3.method_c()
call method_default

上边这个例子说明当我们调用一个不存在的方法时,比如这里的method_c,如果类中定义了__getattr__方法,那么会去调用此函数定义的操作,这就在python中实现了一个默认操作,避免当用户调用一个不存在的方法或属性时解释器会抛出错误,而__getattr__函数后,可以给用户一些提示信息。

文章目录
  1. 1. 反射
|