一、什么是反射
#反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。 #这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
二、四个可以实现自省的函数
适用于类和对象(python中一切皆对象,类也是一种对象)
class Beast: def __init__(self, name, age): self.name = name self.age = age b = Beast('姜春', 25) if hasattr(b,'name'): #按字符串'name'判断有无属性b.name name = getattr(b,'name',None) 等同于b.name,不存在该属性则返回默认值None print(name) if hasattr(b, 'age'): print('{}'.format(getattr(b,'age',None))) setattr(b,'age',78) # 等同于b.age = 78 print('{}'.format(getattr(b,'age',None))) delattr(b,'age') # 等同于del b.age print('{}'.format(getattr(b,'age',None)))
class Beast: def __init__(self, name, age): self.name = name self.age = age self.score = {} def hello(self): print(f'hello,{self.name}') @property def show_score(self): return self.score @show_score.setter def show_score(self,score): self.score[score[0]] = score[1] b = Beast('姜春', 26) # 判断是否有某属性,获取属性 if hasattr(b,'show_score'): if not getattr(b,'show_score','姜春就是一个瓜皮'): setattr(b,'show_score',['洗脚',100]) print(getattr(b,'show_score')) # 设置属性 setattr(b,'show_name',lambda self:self.name+'_DSB') print(getattr(b,'show_name')(b)) # 删除属性 delattr(b,'show_name') print(getattr(b,'show_name','姜春你就是一个瓜皮'))
>>> class FtpServer: ... def serve_forever(self): ... while True: ... inp=input('input your cmd>>: ').strip() ... cmd,file=inp.split() ... if hasattr(self,cmd): # 根据用户输入的cmd,判断对象self有无对应的方法属性 ... func=getattr(self,cmd) # 根据字符串cmd,获取对象self对应的方法属性 ... func(file) ... def get(self,file): ... print('Downloading %s...' %file) ... def put(self,file): ... print('Uploading %s...' %file) ... >>> server=FtpServer() >>> server.serve_forever() input your cmd>>: get a.txt Downloading a.txt... input your cmd>>: put a.txt Uploading a.txt...
(2)导入其他模块,查看其他模块是否有某种方法
#!/usr/bin/env python # -*- coding:utf-8 -*- def test(): print('from the test')
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 """ 5 程序目录: 6 module_test.py 7 index.py 8 9 当前文件: 10 index.py 11 """ 12 13 import module_test as obj 14 15 #obj.test() 16 17 print(hasattr(obj,'test')) 18 19 getattr(obj,'test')()
三、反射的好处
1、实现可插拔机制

class FtpClient: 'ftp客户端,但是还么有实现具体的功能' def __init__(self,addr): print('正在连接服务器[%s]' %addr) self.addr=addr

#from module import FtpClient f1=FtpClient('192.168.1.1') if hasattr(f1,'get'): func_get=getattr(f1,'get') func_get() else: print('---->不存在此方法') print('处理其他的逻辑')
2、动态导入模块
import importlib m = importlib.import_module('test.practice7') #绝对导入 m = importlib.import_module('.practice7',package='test') # 相对导入
四、内置方法
(1)__str__
__str__方法会在对象被打印时自动触发,print功能打印的就是它的返回值,我们通常基于方法来定制对象的打印信息,该方法必须返回字符串类型
class FileOperate: """文件处理类""" def __init__(self,filename): self.filename = filenamedef __str__(self): return f'{self.filename}' F = FileOperate('3.txt') print(F)
3.txt
(2) __del__
__del__会在对象被清理时自动触发。由于Python自带的垃圾回收机制会自动清理Python程序的资源,所以当一个对象只占用应用程序级资源时,完全没必要为对象定制
__del__方法,但在产生一个对象的同时涉及到申请系统资源(比如系统打开的文件、网络连接等)的情况下,关于系统资源的回收,Python的垃圾回收机制便派不上用场了,
需要我们为对象定制该方法,用来在对象被清理时自动触发回收系统资源的操作
class MySQL: def __init__(self,ip,port): self.conn=connect(ip,port) # 伪代码,发起网络连接,需要占用系统资源 def __del__(self): self.conn.close() # 关闭网络连接,回收系统资源 obj=MySQL('127.0.0.1',3306) # 在对象obj被删除时,自动触发obj.__del__()
(3)__repr__
使用方法同__str__
str函数或者print函数--->obj.__str__() repr或者交互式解释器--->obj.__repr__() 如果__str__没有被定义,那么就会使用__repr__来代替输出 注意:这俩方法的返回值必须是字符串,否则抛出异常
(4)__format__
date_dic={ 'ymd':'{0.year}:{0.month}:{0.day}', 'dmy':'{0.day}/{0.month}/{0.year}', 'mdy':'{0.month}-{0.day}-{0.year}', } class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day def __format__(self, format_spec): if not format_spec or format_spec not in date_dic: format_spec='ymd' fmt=date_dic[format_spec] return fmt.format(self) d1=Date(2016,12,29) print(format(d1)) print(format(d1,'mdy'))