python基础:反射(详解)

一、什么是反射

反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。
这一点在项目开发中尤为重要,在不清楚方法或变量在对象中是否存在时,可以通过反射这个特殊的方法或机制来对对象中"未知的"变量或者方法进行操作。

核心是:通过字符串去操作对象的属性和方法,是字符串形式!

二、反射的方法

1、内建函数

方法 意义
getattr(object,name[,default]) 通过name返回object的属性值,当属性不存在,返回default默认值,如果没有default,则抛出异常,name必须是字符串
setattr(object,name,value) 操作object的属性,如有则覆盖,不存在则新增
hasaattr(object,name) 判断对象是否有这个名字的属性,name必须为字符串,有返回True,不存在返回Felse
delattr(object,name) 当通过实例来删除属性时调用此方法

2、反射方法的查找路径

查找路径和继承一致:参考 Python面对对象:继承(详解)
对象本身__dict__---->class的__.dict__---->继承的祖先类(直到object)的__dict__

三、什么对象可以用反射?

在python中只有:实例化对象、类、其他模块(.py结尾的文件)、本模块(.py结尾的文件
只有以上四个才能使用,因为他们都能通过== .== 的方式获取或调用,这也算是一种前提

attr是属性英文的前几个字母,属性指的是类中类变量、实例变量和方法。但是要注意不能是私有的,如果你的变量是以“_”开头,那将无法获取。

四、代码实例

1、实例化对象的反射实例

class People:
    def __init__(self,name):
        self.name = name
    def info(self):
        print("我的名字叫:%s" % self.name)

obj = People("金鞍少年")

#  hasattr 判断对象中是否存在 属性
# =====================================================
print(hasattr(obj, "info"))    # True。因为存在info方法
print(hasattr(obj, "name"))    # True。因为存在name变量
print(hasattr(obj, "age"))     # False。因为不存在age方法或变量

#  getattr 获取对象中的属性
# =====================================================
f1 = getattr(obj, 'info')  # f1 = obj.info
f1()  # 我的名字叫:金鞍少年

# 如果obj中不存在属性,则会报错,可以设置default,返回None、False、True
f2 = getattr(obj, 'xxx', None)
print(f2)  # None

# setattr 为对象设置属性
# =====================================================
setattr(obj, 'age', 18)  # 等同于 obj.age = 18
print(obj.__dict__)  # {'name': '金鞍少年', 'age': 18}

# delattr 删除对象属性
# =====================================================
delattr(obj, 'age')  # 等同于 del obj.age
print(obj.__dict__)  # {'name': '金鞍少年'}

2、类的反射实例

'''
类的反射实例

'''

class Country:
    city = '武汉'
    Attractions = '黄鹤楼'
    def func(self):
        print('武汉有名景点---》黄鹤楼')


# 获取类 Country 的静态属性
print(getattr(Country, 'city'))  # 存在city方法 ,返回 :武汉

# 获取类 Country 的方法
getattr(Country, "func")('Country')   # 武汉有名景点---> 黄鹤楼   ,因为类中方法需要穿一个参数,随便传了一个

# 其他操作和实例化对象操作一致

3、文件(模块)间的反射实例

'''
我是 test.py 文件
'''
name = '我是test.py文件'
class Country:
    city = '武汉'

    def func(self):
        print('武汉有名景点---》黄鹤楼')
#===========================================================================================
'''
我是执行文件
'''
import test
print(test.name) # 我是test.py文件
print(getattr(test.Country,'city'))  # 存在city属性  返回: 武汉
setattr(test.Country,'city','杭州')  # 修改city的属性
print(test.Country.__dict__)
# {'__module__': 'test', 'city': '杭州', 'func': <function Country.func at 0x000002B34EAAC160>, '__dict__': <attribute '__dict__' of 'Country' objects>, '__weakref__': <attribute '__weakref__' of 'Country' objects>, '__doc__': None}

五、练习

1、通过字符串导入模块

temp = "re"  # 要引入的模块
func = "compile"  # 要使用的方法
model = __import__(temp)  # 导入模块
function = getattr(model, func)  # 找到模块中的属性

def main():
    txt = "python 2020"
    pattern = function(r"[0-9]+")  # 这里执行funcation()就等于执行re.compile()函数
    print(model.search(pattern, txt).group())  

if __name__ == '__main__':
    main()

# 结果:2020

2、模拟FTP动态请求过程

class Ftp:
    
    def get(self):
        print('下载文件')

    def put(self):
        print('上传文件')

    def login(self):
        print('登录')
        
    def run(self):
        while True:
            choice = input('>>>请输入命令: ').strip()
            if hasattr(self, choice):
                method = getattr(self, choice)
                method()
            else:
                print('命令不存在')

obj = Ftp()
obj.run()
发布了48 篇原创文章 · 获赞 43 · 访问量 5021

猜你喜欢

转载自blog.csdn.net/weixin_42444693/article/details/104717237