Bootstrap

python反射详细解释

一、反射的定义

反射的本质:

        是通过字符串去调用某个对象的方法/属性,或者调用模块中的函数等。

通俗点说:

        用字符串数据类型的名字 来操作这个名字对应的 函数\实例变量\绑定方法\各种方法

二、python中提供了四个重要的方法 

  • getattr()  获取对象属性/对象方法
  • hasattr()   判断对象是否有对应的属性及方法
  • delattr()   删除指定的属性
  • setattr()  为对象设置内容
hasattr查询
setattr新增
getattr获取
delattr

删除

 

class Person:
    # 类属性
    Role = "法师"
    # 私有属性
    __weight = 120

    def __init__(self):
        #  实例属性
        self.name = 'mike'
        self.age = 20

    #  普通方法
    def say(self):
        return '普通方法'

    # 私有方法
    def  __say2(self):
        return '私有方法'

    # 类方法
    @classmethod
    def say3(cls):
        obj = Person()
        print(obj.name)
        return '类方法'

1、getattr()方法

这个方法是根据字符串去某个模块中寻找方法等

1.1、反射对象的 普通属性/普通方法

obj = Person()
print(getattr(obj, 'name'))  # 反射对象的 普通变量  正常用法是 obj.name
print(getattr(obj, 'say'))   # 方法的内存地址 后面结()表示执行这个方法
getattr(obj, 'say')()        # 反射对象的 普通方法  正常用法是 obj.say()


################################################

mike
<bound method Person.say of <__main__.Person object at 0x00000206296B4EE0>>
普通方法

Process finished with exit code 0

 1.2、反射类的 类属性/类方法

print(getattr(Person, 'Role')) # 反射类中的 类属性  正常用法是 Person.Role

getattr(Person, 'say3')()       # 反射类中的 类方法  正常用法是 Person.say3()



#######################################################
法师
mike
类方法

Process finished with exit code 0

1.3、反射当前脚本的 变量/函数

import sys

name = 'mike'
def  func1():
    print('普通函数')

# 反射当前脚本的变量  正常应该是 print(name)
obj = getattr(sys.modules['__main__'],'name')
print(obj)

# 反射当前脚本的函数  正常应该是 func1()
obj = getattr(sys.modules['__main__'],'func1')
obj()


##############################################################

mike
普通函数

Process finished with exit code 0

1.4、反射被导入模块的 变量/函数

被导入模块 test04.py 

name = 'mike'
def  func1():
    print('普通函数')

当前脚本 a.py

import test04


# 反射被导入模块的变量    正常应该是 test04.name
obj = getattr(test04, 'name')
print(obj)


# 反射被导入模块的方法  正常应该是 test04.func1()
obj = getattr(test04, 'func1')
obj()





################################################
mike
普通函数

Process finished with exit code 0

2、hasattr()方法

这个方法是根据字符串去判断某个模块中该方法是否存在  返回布尔类型

obj =  Person()
#  判断对象是否有某个属性
print(hasattr(obj, 'name'))
print(hasattr(obj, 'xxx'))



#################################################
True
False

Process finished with exit code 0
拓展:

封装一个函数结合getattr()方法和callable()方法使用

 

def fanshe(a,b):
    # 判断类或者对象  能不能反射某一个变量  如果能反射返回True
    if hasattr(a, b):
        # 判断能反射的变量是不是一个方法,如果是可执行的,如果是我们直接可以调用
        if callable(getattr(a, b)):
            # 执行方法
            getattr(a, b)()
        else:
            # 打印属性
            print(getattr(a, b))
    else:
        print('没有这个属性/方法')




a = Person()

# 反射一个对象里不存在的属性
b = 'xxx'
fanshe(a,b)

# 反射一个对象存在属性
b = 'name'
fanshe(a,b)

#  反射一个对象不存在方法
b = 'say222222'
fanshe(a,b)

# 反射一个对象存在方法
b = 'say'
fanshe(a,b)


#########################################
没有这个属性/方法
mike
没有这个属性/方法
普通方法

Process finished with exit code 0

3、setattr()方法

这个方法是根据字符串去某个模块中设置方法,可以动态添加属性和方法

obj = Person()
# 修改之前 anme 属性
print(getattr(obj, 'name'))
setattr(obj, 'name', "吴彦祖")
#  修改之后 name 属性
print(getattr(obj, 'name'))



#######################################################################

mike
吴彦祖

Process finished with exit code 0

 4、delattr()方法

这个方法是根据字符串去某个模块中删除方法

obj = Person()
# 删除之前判断是否有这个属性,如果有则打印
if hasattr(obj, 'age'):
    print(getattr(obj, 'age'))
else:
    print('没有这个属性')

# 删除该属性
delattr(obj, 'age')

# 建议是否已经删除
if hasattr(obj, 'age'):
    print(getattr(obj, 'age'))
else:
    print('没有这个属性')  



##################################################################
20
没有这个属性

Process finished with exit code 0

 

;