Python 高级 -- 反射

在 Java 中我们经常使用反射,而且大部分的 Java 框架都是基于反射实现的。那么 Python 中是否也有反射呢?答案是肯定的。那么 Python 中的反射如何使用呢?

概念

有时候我们会碰到这样的需求,需要执行对象的某个方法,或是需要对对象的某个字段赋值,而方法名或是字段名在编码代码时并不能确定,需要通过参数传递字符串的形式输入。举个具体的例子:需要调用的方法名是前端通过接口传入的,而在代码编写时根本无法确定前端会传入具体的那个方法名,因此无法确定调用哪个方法,这时,我们需要通过某种机制访问未知的属性。这个机制被称为反射。

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

相关方法

  • dir([obj]):

调用这个方法将返回包含 obj 大多数属性名的列表(会有一些特殊的属性不包含在内)。obj 的默认值是当前的模块对象。

  • hasattr(obj, attr):

这个方法用于检查 obj 是否有一个名为 attr 的值的属性,返回一个布尔值。

  • getattr(obj, attr):

判断对象 obj 是否包含名为 attr 的特性,将返回 obj 中名为 attr 值的属性的值,例如如果 attr 为 bar,则返回 obj.bar

  • setattr(obj, attr, val):

调用这个方法将给 obj 的名为 attr 的值的属性赋值为 val。例如如果 attr 为 bar,setattr(obj,'bar',val)相当于 obj.bar = val

  • delattr(obj, name)

与 setattr() 相关的一组函数,删除模块中某个变量或者函数。参数是由一个对象(记住python中一切皆是对象)和一个字符串组成的。string 参数必须是对象属性名之一。该函数删除该 obj 的一个由 string 指定的属性。delattr(bar,'age')

实例

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
class Cat(object):
def __init__(self, name="kitty"):
self.name = name

def sayHi(self):
print(self.name, "say Hi")

kit = Cat()
print("name is:", kit.name)
kit.sayHi()

print(dir(kit))
print(dir(Cat))

# 判断是否方法或属性是否存在
print(hasattr(kit,'sayHi'))
print(hasattr(kit,'name'))

# 设置 name 属性
setattr(kit, 'name', 'xiaohei')
print("name is:", kit.name)

# 通过反射的方式调用 sayHi 方法
func = getattr(kit, 'sayHi')
func()

# 删除属性
delattr(kit, name)
print("name is:", kit.name)

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
name is: kitty
kitty say Hi
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'sayHi']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'sayHi']
True
True
name is: xiaohei
xiaohei say Hi
Traceback (most recent call last):
File "reflection.py", line 28, in <module>
delattr(kit, name)
NameError: name 'name' is not defined
hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
  • 本文作者: hoxis | 微信公众号【不正经程序员】
  • 本文链接: https://hoxis.github.io/python-reflection.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!
0%