反射
# 反射
# 简介
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
反射方法:
- getattr 根据字符串的形式,去对象中找成员。
- hasattr 根据字符串的形式,去判断对象中是否有成员。
- setattr 根据字符串的形式,去判断对象动态的设置一个成员(内存)
- delattr 根据字符串的形式,去判断对象动态的设置一个成员(内存)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
# 对象的反射
class Foo:
def __init__(self):
self.name = 'egon'
self.age = 51
def func(self):
print('hello')
egg = Foo()
print(hasattr(egg, 'name')) # 先判断name在egg里面存在不存在,结果是True
print(getattr(egg, 'name')) # 如果为True它才去得到,结果是egon
print(hasattr(egg, 'func')) # 结果是True
print(getattr(egg, 'func')) # 得到的是地址<bound method Foo.func of <__main__.Foo object at 0x0000000001DDA2E8>>
getattr(egg, 'func')() # 在这里加括号才能得到,因为func是方法,结果是hello
# 一般用法如下,先判断是否hasattr,然后取getattr
if hasattr(egg, 'func1'):
getattr(egg, 'func')() # 结果是hello
else:
print('没找到')
"""
True
egon
True
<bound method Foo.func of <__main__.Foo object at 0x000002086985D280>>
hello
hello
"""
class A():
def __init__(self):
self.bb = "222"
def aa(self):
print("aa", self.bb)
b = A()
print(hasattr(b, "aab"))
print(getattr(b, "aa")())
# - setattr 根据字符串的形式,去判断对象动态的设置一个成员(内存)
# - delattr 根据字符串的形式,去判断对象动态的设置一个成员(内存)
print(setattr(b, "bb", "2"))
print(getattr(b, "aa")())
delattr(b, "bb")
# print(getattr(b, "aa")()) # AttributeError: 'A' object has no attribute 'bb'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 对类的反射
class Foo:
f = 123
@classmethod
def class_method_dome(cls):
print('class_method_dome')
@staticmethod
def static_method_dome():
print('static_method_dome')
print(hasattr(Foo, 'class_method_dome')) # 结果是True
method = getattr(Foo, 'class_method_dome')
method() # 结果是class_method_dome
print(hasattr(Foo, 'static_method_dome')) # 结果是True
method1 = getattr(Foo, 'static_method_dome')
method1() # 结果是static_method_dome
"""
True
class_method_dome
True
static_method_dome
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 当前模块的反射
import sys
def s1():
print('s1')
def s2():
print('s2')
this_module = sys.modules[__name__] # 获取所有模块名称
print(this_module.__dict__)
print(hasattr(this_module, 's1'))
print(getattr(this_module, 's2')())
"""
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002BE3FCB0910>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/YouYizhang/Desktop/python-YYZ/1. Python基础/04、python面向对象/6. 反射/3. 当前模块的反射.py', '__cached__': None, 'sys': <module 'sys' (built-in)>, 's1': <function s1 at 0x000002BE3FC96310>, 's2': <function s2 at 0x000002BE40177A60>, 'this_module': <module '__main__' from 'C:/Users/YouYizhang/Desktop/python-YYZ/1. Python基础/04、python面向对象/6. 反射/3. 当前模块的反射.py'>}
True
s2
None
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 其他模块的反射
# 一个模块中的代码
def test():
print('from the test')
"""
程序目录:
module_test.py
index.py
当前文件:
index.py
"""
# 另一个模块中的代码
# import module_test as obj
# obj.test()
# print(hasattr(obj, 'test'))
# getattr(obj, 'test')()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 反射的应用
了解了反射的四个函数。那么反射到底有什么用呢?它的应用场景是什么呢?
现在让我们打开浏览器,访问一个网站,你单击登录就跳转到登录界面,你单击注册就跳转到注册界面,其实你单击的其实是一个个的链接,每一个链接都会有一个函数或者方法来处理。
没学反射之前的解决方式
class User:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
while 1:
choose = input('>>>').strip()
if choose == 'login':
obj = User()
obj.login()
elif choose == 'register':
obj = User()
obj.register()
elif choose == 'save':
obj = User()
obj.save()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
学了反射之后解决方式
class User:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
user = User()
while 1:
choose = input('>>>').strip()
if hasattr(user, choose):
func = getattr(user, choose)
func()
else:
print('输入错误。。。。')
"""
>>>login
欢迎来到登录页面
>>>save
欢迎来到存储页面
>>>
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
编辑 (opens new window)
上次更新: 2023/05/17, 23:08:21