目录
反射
python提供自省的四个方法:
hasattr(object,name) 判断object中有没有有个name字符串对应对应的方法和属性
class demo: name = 'chen' age = '22' def test_func(self): print("存在") hasattr(demo, 'test_func') #True hasattr(demo, 'name') #True hasattr(demo, 'date') #False
(常用)getattr(object,name,default=None) 根据name字符串寻找object中对应的数据属性或函数属性,相当于object.name
class demo: name = 'chen' age = '22' def test_func(self): print("存在") getattr(demo, 'test_func') #<function demo.test_func at 0x00000264F0ABA9D8> getattr(demo, 'name') #chen getattr(demo, 'date') #报错
setattr(object,name,value) 根据name字符串去设置或修改object中相对应的数据属性或函数属性,相当于object.name=value
class demo: name = 'chen' age = '22' def test_func(self): print("存在") #设置数据属性 setattr(demo,'date','2018/11/21') print(getattr(demo, 'date')) #2018/11/21 #设置函数属性 setattr(demo,'test2_func',lambda x:x+2) print(getattr(demo, 'test2_func')(8)) #10
delattr(object,name) 根据name字符串去删除object中相对应的数据属性或函数属性,相当于del object.name
class demo: name = 'chen' age = '22' def test_func(self): print("存在") delattr(demo,'name')
反射使用类中用到的三个内置函数
(常用)_getattr_ 当访问的属性找不要的时候执行这个这个函数
class demo: def __init__(self,name,age): self.name = name self.age = age def __getattr__(self, item): print("不存在%s属性"%item) d1 = demo('chen',22) #调用不存在的属性 d1.data #不存在data属性
补充:
_getattribute_ 当访问属性时,无论属性存不存在,都会执行,当与_getattr_函数同时存在时,优先执行_getattribute_ ,忽略_getattr_函数。
所以_getattr_是在_getattribute_ 中抛出一个AttributrError时才会执行
class demo: def __init__(self,name,age): self.name = name self.age = age def __getattr__(self, item): #会被忽略 print("这里是getattr") def __getattribute__(self, item): print("这里是getattribute") # raise AttributeError('抛出异常') d1 = demo('chen',22) #调用不存在的属性 d1.data #这里是getattribute class demo: def __init__(self,name,age): self.name = name self.age = age def __getattr__(self, item): print("这里是getattr") def __getattribute__(self, item): print("这里是getattribute") raise AttributeError('抛出异常') #抛出异常,会调用__getattr__方法去执行 d1 = demo('chen',22) #调用不存在的属性 d1.data #这里是getattribute 这里是getattr
_setattr_ 当赋值属性值时执行这个函数
class demo: def __init__(self,name,age): self.name = name #赋值操作 self.age = age #赋值操作 def __setattr__(self, key, value): print("key:%s value:%s"%(key,value)) self.__dict__[key]=value d1 = demo('chen',22) #key:name value:chen key:age value:22
_delattr_ 当删除属性事执行这个函数
class demo: def __init__(self,name,age): self.name = name #赋值操作 self.age = age #赋值操作 def __delattr__(self, item): print("删除%s"%item) self.__dict__.pop(item) d1 = demo('chen',22) del d1.name #删除name
变量赋值操作的自定制之所有字符串大写
class demo: def __init__(self,name,age): self.name = name #赋值操作 self.age = age #赋值操作 def __setattr__(self, key, value): if type(value) is str: self.__dict__[key] = value.upper() #制定大写 else: self.__dict__[key] = value d1 = demo('chen',22) print(d1.__dict__) #{'name': 'CHEN', 'age': 22}
利用继承二次包装标准类
class List(list): def append(self, value): if type(value) is str: super().append(value) else: print('只能添加字符串类型') def show_midlle(self): #求列表中间的value mid_index=int(len(self)/2) return self[mid_index] l1=List('chen') l1.append(12) #只能添加字符串类型 l1.show_midlle() #e
利用授权二次包装标准类
授权也是一种包装,但不是通过继承去实现,利用_getattr_实现
import time class FileHandle: def __init__(self,filename,mode='r',encoding='utf-8'): #已实现的功能,依然用原来的功能 self.file=open(filename,mode,encoding=encoding) # 定制在写入文件时,写入时间的写函数 def write(self,line): t=time.strftime('%Y-%m-%d %X') self.file.write('%s %s' %(t,line)) #如果访问的属性不纯在 def __getattr__(self, item): return getattr(self.file,item) f1=FileHandle('a.txt','w+',encoding='utf-8') f1.write('第一条 ') f1.write('第二条 ') f1.write('第三条 ')
2018-11-21 19:11:07 第一条 2018-11-21 19:11:07 第二条 2018-11-21 19:11:07 第三条
动态导入模块
# 导入的是m1,不是m1下的t文件 # 这样导入的是路径最顶层的模块 module_t = __import__('m1.t') # print(module_t) #<module 'm1' (namespace)> module_t.t.test3() #这里是t模块 #利用模块导入 import importlib #导入的是m1下的t文件 m = importlib.import_module("m1.t") print(m) # <module 'm1.t' from 'F:\PyCharm 2018.2.3\PycharmProjects\chen\day13\m1\t.py'> m.test3() #这里是t模块