python3基础-反射、内置attr属性、动态导入的问题
一 反射
反射指的是通过字符串来操作对象的属性
class People: nationality='china' def __init__(self,name): self.name=name def eat(self): print("%s吃水果"%self.name) p1 = People('苏苏') #hasattr(object,name) print(hasattr(p1,'name')) #按字符串‘name’ 判断有无属性p1.name 返回True print(hasattr(p1,'eat')) #按字符串‘eat’ 判断有无属性p1.eat #getattr(object,'name',default) print(getattr(p1,'name',None)) #等同于p1.name 不存在该属性则返回默认值none ; func = getattr(p1,'eat') #p1.eat func() #则输出的是 susu 吃水果 #setattr(object,'name',value) setattr(p1,'name','SB') #==P1.name='SB' 直接修改属性 print(getattr(p1,'name',None)) #则输出的是 SB #新增一个属性 setattr(p1,'age',28) print(p1.__dict__) #输出的是{'name': 'SB', 'age': 28} #delattr(object,'name') delattr(p1,'name') print(getattr(p1,'name',None)) #则输出的是 None
基于反射可以灵活地操作对象的属性,比如将用户交互的结果反射到具体的功能执行
二 内置attr属性
#注意: __getattr__ __delattr__ __setattr__ 触发条件是实例化后才能触发 class People: nationality='china' def __init__(self,name): self.name=name # __getattr__:当使用点号获取实例属性时,如果属性不存在就自动调用__getattr__方法 def __getattr__(self, item): print('__getattr__:调用一个不存在的对象属性时候,执行',item) #删除属性的时候会触发 def __delattr__(self, item): print('__delattr__删除一个属性时候,执行',item) def __setattr__(self, key, value): print('__setattr__修改/添加一个属性时候') #self.key = value #RecursionError: maximum recursion depth exceeded while calling a Python object #因为这个也是在设置一个属性,当设置这个属性的时候,也会触发__setattr__,这样就会一直循环,最后报错,所有使用self.__dict__[key] = value操作 self.__dict__[key]=value p1 = People('小苏') #设置一个属性操作的时候,执行__setattr__; __init__中的self.name 传递给key name 传递给value print(p1.name) print(getattr(p1,'哈哈哈')) #属性不存在就自动调用__getattr__方法 print(getattr(p1,'name')) #属性存在,则就返回属性值 p1.ssssss #属性不存在就自动调用__getattr__方法 print(p1.__dict__) p1.age=18 print(p1.__dict__) del p1.name #删除存在的属性,会触发__delattr__ del p1.height#删除不存在的属性,也会触发__delattr__
以上代码执行
__setattr__修改/添加一个属性时候 小苏 __getattr__:调用一个不存在的对象属性时候,执行 哈哈哈 None 小苏 __getattr__:调用一个不存在的对象属性时候,执行 ssssss {'name': '小苏'} __setattr__修改/添加一个属性时候 {'name': '小苏', 'age': 18} __delattr__删除一个属性时候,执行 name __delattr__删除一个属性时候,执行 height
三 动态导入
a=1 print("111",a) def dev1(): print("dev.py") return 1
def test1(): return 'test1' def _test2(): return 'test2'
#-src # |-----dev.py # |-----动态导入模块.py # |-----m1目录 # |-----test.py print('----方法1') from m1 import test test.test1() #方法2 #调用m1 目录下 test文件里面的test1 print('----方法2') t1 = __import__('m1.test') print(t1) print(t1.test.test1()) #方法3 #调用相同目录下的dev文件 print('----方法3') t1 = __import__('dev') print(t1) print(t1.dev1()) #方法4 #调用m1 目录下 所有的文件 print('----方法4') from m1.test import * print(test1()) #_test2() 调用模块 函数单下划线开头就无法调用成功 #方法5 #调用m1 目录下 test print('----方法5') import importlib t1 = importlib.import_module('m1.test') print(t1) print(t1.test1())
以上代码执行结果如下:
----方法1 test1 ----方法2 <module 'm1' (namespace)> test1 ----方法3 111 1 <module 'dev' from 'D:\\pyAuto\\pythonDay\\pythonbase\\类\\dev.py'> dev.py 1 ----方法4 test1 ----方法5 <module 'm1.test' from 'D:\\pyAuto\\pythonDay\\pythonbase\\类\\m1\\test.py'> test1