反射就是通过字符串的形式,导入模块,通过字符串的形式,去模块寻找制定函数并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动。
例子:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def show(self):
return self.x + self.y
p = Point(2, 3)
p.__dict__
{'x': 2, 'y': 3}
# 实例化运用方法
p.show()
5
# 反射 获取类的信息
getattr(p, 'show')()
5
# 发射 添加类的信息
setattr(p, "language", "python")
p.__dict__
{'language': 'python', 'x': 2, 'y': 3}
p.language
python
# 反射 判断是否有该类的信息
hasattr(p, "language")
True
# 反射 删除类的信息
delattr(p, "language")
p.__dict__
{'x': 2, 'y': 3}
setattr的对象是实例,给函数动态增加方法需要将函数转化为方法,转化方法types.MethodType
def lst(self):
print(self.x, self.y)
import types
setattr(p, "lst", types.MethodType(lst, p))
p.lst()
2 3
通过getattr来执行本身函数执行
class Command:
def cmd1(self):
print("cmd1")
def cmd2(self):
print("cmd2")
def run(self):
while True:
cmd = input(">>>")
if cmd == "quit"
return
getattr(self, cmd, lambda : print("not found cmd {}".format(cmd)))()
cmd = Command()
cmd.run()
>>>cmd1
cmd1
>>>cmd2
cmd2
>>>cmd3
not found cmd cmd3
>>>quit
__getattr__
__setattr__
__delattr__
当一个类定义了__getattr__
方法时,如果访问不存在的成员,会调用__getattr__
方法
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __getattr__(self, name):
return "can not found {} property".format(name)
def show(self):
return self.x + self.y
p = Point(1, 2)
p.x
1
p.z
'can not found z property'
属性查找优先级 __dict__
> __class__.__dict__
> __getattr__
p.__dict__
{'x': 1, 'y': 2}
p.__class__.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'Point' objects>,
'__doc__': None,
'__getattr__': <function __main__.Point.__getattr__>,
'__init__': <function __main__.Point.__init__>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Point' objects>,
'show': <function __main__.Point.show>})
当一个类实现__setattr__
时,任何地方对这个类的对象增加属性,或者对现有属性赋值,都会调用__setattr__
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __setattr__(self, name, value):
print('set {} to {}'.format(name, value))
self.__dict__[name] = value
p = Point(1, 2)
set x to 1
set y to 2
p.__dict__
{'x': 1, 'y': 2}
当需要对实例属性修改,做一些额外操作的时候,可以使用__setattr__
当一个类实现__delattr__
时,任何地方对这个类的对象删除属性,都会调用__delattr__
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __delattr__(self, name):
print('remove property {}'.format(name))
self.__dict__.pop(name)
p = Point(1, 2)
p.__dict__
{'x': 1, 'y': 2}
del p.x
remove property x
p.__dict__
{'y': 2}
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __getattribute__(self, name):
return "overwrite __dict__"
p = Point(1, 2)
p.x
'overwrite __dict__'
p.y
'overwrite __dict__'
从上述可得知属性优先级:
__getattribute__ > __dict__ > __class__.__dict__ > __getattr__
以梦为马 不负韶华 归来仍是少年
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。