Jusene's Blog

python 反射

字数统计: 636阅读时长: 3 min
2018/06/17 Share

反射

反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!

反射可以在运行的时候获取类的信息,如:

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__
CATALOG
  1. 1. 反射