反射
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
反射可以在运行的时候获取类的信息,如:
1 | class Point: |
2 | def __init__(self, x, y): |
3 | self.x = x |
4 | self.y = y |
5 | |
6 | def print(self): |
7 | return self.x + self.y |
8 | |
9 | p=Point(1,2) |
10 | p.__dict__ |
11 | {'x': 1, 'y': 2} |
* getattr setattr hasattr *
1 | getattr(p, 'print')() |
2 | 3 |
3 | |
4 | setattr(p,'example','python') |
5 | p.example |
6 | python |
7 | |
8 | hasattr(p,'example') |
9 | True |
setattr对象是实例,给函数动态增加方法需要先把函数转化为方法,转化方法types.MethodType
1 | def mm(self): |
2 | print(self.x) |
3 | |
4 | import types |
5 | setattr(p,'mm',types.MethodType(mm,p)) |
6 | |
7 | p.mm() |
8 | 1 |
通过getattr获取本身的函数执行:
1 | class Command: |
2 | def cmd1(self): |
3 | print('cmd1') |
4 | def cmd2(self): |
5 | print('cmd2') |
6 | def run(self): |
7 | while True; |
8 | cmd = input('>>>') |
9 | if cmd == 'quit': |
10 | return |
11 | getattr(self, cmd, lambda x:print('not found cmd {}'.format(cmd)))() |
* getattr setattr delattr *
- getattr
1 | class A: |
2 | def __init__(self,x): |
3 | self.x = x |
4 | def __getattr__(self,name): |
5 | return 'can not found {} property'.format(name) |
6 | |
7 | a=A(1) |
8 | a.x |
9 | 1 |
10 | a.y |
11 | can not found y property |
当一个类定义了__getattr__
方法时,如果访问不存在的成员,会调用__getattr__
方法
1 | a=A(1) |
2 | a.__dict__ |
3 | {'x': 1} |
4 | a.__class__.__dict__ |
5 | mappingproxy({'__dict__': <attribute '__dict__' of 'A' objects>, |
6 | '__doc__': None, |
7 | '__getattr__': <function __main__.A.__getattr__>, |
8 | '__init__': <function __main__.A.__init__>, |
9 | '__module__': '__main__', |
10 | '__weakref__': <attribute '__weakref__' of 'A' objects>}) |
11 | 属性查找: |
12 | __dict__ > __class__.__dict__ > getattr |
- setattr
1 | class A: |
2 | def __init__(self,n): |
3 | self.x = n |
4 | def __setattr__(self,name,value): |
5 | print('set {} to {}'.format(name,value)) |
6 | |
7 | a = A(1) |
8 | set x to 1 |
9 | a.x |
10 | AttributeError: 'A' object has no attribute 'x' |
11 | a.__dict__ |
12 | {} |
13 | |
14 | class A: |
15 | def __init__(self,n): |
16 | self.x = n |
17 | def __setattr__(self,name,value): |
18 | print('set {} to {}'.format(name,value)) |
19 | self.__dict__[name] = value |
20 | |
21 | a = A(1) |
22 | set x to 1 |
23 | a.x |
24 | 1 |
25 | a.__dict__ |
26 | {'x': 1} |
当一个类实现__setattr__
时,任何地方对这个类的对象增加属性,或者对现有属性赋值,都会调用__setattr__
当需要对实例属性修改,做一些额外操作的时候,可以使用__setattr__
- delattr
1 | class A: |
2 | def __init__(self): |
3 | self.x = 3 |
4 | def __delattr__(self, name): |
5 | print('can not remove property {}'.format(name)) |
6 | |
7 | a=A() |
8 | del a.x |
9 | can not remove property x |
10 | a.y = 2 |
11 | del a.y |
12 | can not remove property y |
当一个类实现__delattr__
时,任何地方对这个类的对象删除属性,都会调用__delattr__
- getattribute
1 | class A: |
2 | def __init__(self): |
3 | self.x = 3 |
4 | def __getattribute__(self,name): |
5 | return 'haha' |
6 | |
7 | a = A() |
8 | a.x |
9 | haha |
10 | |
11 | __getattribute__ > __dict__ > __class__.__dict__ > __getattr__ |