Python中的反射以及应用 --Python3

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (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')

猜你喜欢

转载自blog.csdn.net/Thanlon/article/details/94548033