版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)
1、为什么使用反射?
python面向对象中的反射就是通过字符串获取模块、对象或类的属性,进行操作。
没有使用反射:
deal.py:
# coding:utf-8
def func01():
print('func01')
def func02():
print('func02')
def func03():
print('func03')
# coding:utf-8
import deal
while True:
print('''
系统支持的函数:
1、f1
2、f2
3、f3
4、f4
''')
func_name = input(' 请输入您要执行的函数序号:')
if func_name == '1':
deal.func01()
elif func_name == '2':
deal.func02()
elif func_name == '3':
deal.func03()
使用反射实现相同功能的程序:
# coding:utf-8
import deal
from types import FunctionType
while True:
print('''
系统支持的函数:
1、f1
2、f2
3、f3
4、f4
''')
func_name = input(' 请输入您要执行的函数序号:')
# 使用反射:
if hasattr(deal, func_name):
func_or_value = getattr(deal, func_name) # func_name是字符串,根据字符串去模块中找与之同名的成员
if isinstance(func_or_value, FunctionType): # 可能是值,也可能是函数,所以在这里需要去判断
func_or_value()
else:
print(func_or_value)
else:
print('deal模块中不存在输入的函数名!')
在deal模块不断增加函数时,不使用反射会写很多判断条件。而使用反射,很明显程序中可以少写很多代码。
2、getattr函数
getattr函数根据字符串为参数去对象(对象、类、模块)中寻找与之同名的成员。
根据字符串为参数去模块中寻找与之同名的成员:
module.py:
# coding:utf-8
name = 'Thanlon'
def f1(arg):
print(arg, 'is good!')
# coding:utf-8
import module
v = getattr(module,'name')
print(v)
func_name = getattr(module,'f1')
func_name('Thanlon')
'''
Thanlon
Thanlon is good!
''
根据字符串为参数去类和对象中寻找与之同名的成员:
# coding:utf-8
class Foo(object):
country = 'China'
def f1(self0):
print('f1')
value_name = getattr(Foo, 'country') # 静态字段
print(value_name)
obj = Foo()
value_name = getattr(obj, 'country')# 实例变量
print(value_name)
func_name = getattr(Foo, 'f1') # 函数
print(func_name)
func_name = getattr(obj, 'f1') # 方法
print(func_name)
'''
China
China
<function Foo.f1 at 0x000001EAF1D9D7B8>
<bound method Foo.f1 of <__main__.Foo object at 0x000001EAF1DAD240>>
'''
练习:
# coding:utf-8
class User(object):
func_lst = ['register', 'login']
def register(self):
print('register')
def login(self):
print('login')
def run(self):
print('''
系统支持的函数:
1、注册
2、登录
''')
choice = int(input('请输入要执行序号(序号对应相应的方法):'))
func_name = User.func_lst[choice - 1] # 类变量优先通过类去调用,这里用User;当然也可以用对象self
# func = getattr(User, func_name) # User.register、User.login;类.函数
# func(self)
func = getattr(self, func_name) # self.register、self.login;对象.方法
func()
obj = User()
obj.run()
obj2 = User()
obj2.run()
3、hasattr函数
hasattr:根据字符串形式,去判断对象中是否有成员
# coding:utf-8
import module
v_ret = hasattr(module,'name')
func_ret = hasattr(module,'f1')
print(v_ret,func_ret)
'''
True True
'''
4、setattr函数
setattr:根据字符串形式,动态去设置一个成员(内存)
# coding:utf-8
import module
setattr(module,'lover','Kiku')
v = getattr(module,'lover')
print(v)
setattr(module,'f2',lambda x:x*2)
func_name = getattr(module,'f2')
print(func_name)
print(func_name(1996))
'''
Kiku
<function <lambda> at 0x0000020189A3C1E0>
3992
'''
注意:如果设置属性,为让大家明白,需要在清楚写明类中有哪些设置的成员,如在 _ _ init _ _方中self.age = None。不建议使用setattr方法。
# coding:utf-8
import module
class Foo(object):
def __init__(self, name):
self.name = name
self.age = None # 等待setattr
obj = Foo('Thanlon')
setattr(obj, 'age', '23')
setattr(Foo, 'age', '23')
print(getattr(Foo,'age'))
5、delattr函数
delattr:根据字符串形式,动态删除一个成员(内存)
# coding:utf-8
import module
setattr(module,'lover','Kiku')
v = getattr(module,'lover')
print(v)
setattr(module,'f2',lambda x:x*2)
func_name = getattr(module,'f2')
print(func_name)
print(func_name(1996))
delattr(module,'lover')
v = getattr(module,'lover')
delattr(module,'f2')
func_name = getattr(module,'f2')