python中的反射

一 概述

python中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象,都可以使用反射

用于反射的几种方法:

hasattr:hasattr(object, name)判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False

getattr:getattr(object, name, default=None)  获取对象的属性或方法,没有则报错(可以设置默认返回值)。需要注意的是,如果获取的是对象的方法,返回的是方法的内存地址,我们可以添加()运行。实际

应用中:hasattr和getattr配套使用。

setattr:给对象的属性赋值,若属性不存在,先创建后赋值

delattr:删除该对象指定的一个属性,没有则报错

二 实例应用

2.1 对象应用反射

class Studnet(object):

    school = '社大'

    def __init__(self, name, age, score):
        self.name = name
        self.__age = age
        self.__score = score

    def get_age(self):
        print('%s 年龄为:%s' %(self.name, self.__age))

    def get_score(self):
        print('%s 分数为:%s' %(self.name, self.__score))


s = Studnet('joe',18,80)

# 检测是否含有某属性或方法
print(hasattr(s, 'name'))       # True
print(hasattr(s, 'get_age'))    # True
print(hasattr(s, 'xxx'))        # True

# 获取属性
n = getattr(s, 'name')
print(n)
func = getattr(s, 'get_age')
print(func)                 # <bound method Studnet.get_age of <__main__.Studnet object at 0x000001D653866128>>
func()

# getattr(s, 'xxx')         # 报错 AttributeError: 'Studnet' object has no attribute 'xxx'
print(getattr(s,'xxx','不存在此属性'))

# 设置属性
setattr(s, 'addr', '地球村')
setattr(s, 'get_name', lambda self:self.name)
print(s.__dict__)
print(s.get_name(s))

# 删除属性
delattr(s,'addr')
delattr(s,'get_name')
# delattr(s,'xxx')          # 不存在,则报错

print(s.__dict__)
View Code

2.2 类应用反射

class Studnet(object):

    school = '社大'

    def __init__(self, name, age, score):
        self.name = name
        self.__age = age
        self.__score = score

    def get_age(self):
        print('%s 年龄为:%s' %(self.name, self.__age))

    def get_score(self):
        print('%s 分数为:%s' %(self.name, self.__score))



# 检测是否含有某属性或方法
print(hasattr(Studnet, 'name'))         # False
print(hasattr(Studnet, 'school'))       # True

# 获取属性
print(getattr(Studnet, 'get_age'))      # <function Studnet.get_age at 0x000002E0558712F0>

# 设置属性
setattr(Studnet, 'addr', '地球村')
print(Studnet.__dict__)

# 删除属性
delattr(Studnet,'addr')

print(Studnet.__dict__)
View Code

2.3 模块应用反射

import sys


def func1():
    print('func1执行结果')

def func2():
    print('func2执行结果')


this_module = sys.modules[__name__]    # 获取当前模块(py文件)

print(hasattr(this_module, 'func1'))   # True
getattr(this_module, 'func2')()        # func2执行结果
模块内部使用反射
# module_test.py文件
def func1():
    print('module_test func1')

def func2():
    print('module_test func2')


# 调用module_test.py
import module_test

print(hasattr(module_test,'func1'))  # True
getattr(module_test,'func1')()       # module_test func1
getattr(module_test,'func2')()       # module_test func2
导入模块使用反射

三 反射之好处

3.1 实现可插拔机制

我们可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用。

class Foo(object):

    def __init__(self):
        pass

    def func1(self):
        print('required_module func1')
required_module.py
import required_module

rm = required_module.Foo()

if hasattr(rm,'func1'):
    get_func1 = getattr(rm,'func1')
    get_func1()
else:
    print('不存在时执行此逻辑')

if hasattr(rm,'func2'):
    get_func2 = getattr(rm,'func2')
    get_func2()
else:
    print('不存在时执行此逻辑')
引用py文件

3.2 动态导入模块

import importlib

required_module = __import__('required_module')   # 解释器内部使用调用方式

required_module = importlib.import_module('required_module')     # 利用importlib导入,与__import__效果一致,建议使用
引用py文件

注:以上例子required_module.py文件与调用py文件在同一目录下

posted @ 2018-07-19 17:30  Joe1991  阅读(113)  评论(0)    收藏  举报