一、反射
python是动态语言,而反射(reflection)机制被视为动态语言的关键。
反射机制指的是在程序的运行状态中
对于任意一个类,都可以知道这个类的所有属性和方法;
对于任意一个对象,都能够调用他的任意方法和属性。
这种动态获取程序信息以及动态调用对象的功能称为反射机制。
在python中实现反射非常简单,在程序运行过程中,如果我们获取一个不知道存有何种属性的对象,若想操作其内部属性,可以先通过内置函数dir来获取任意一个类或者对象的属性列表,列表中全为字符串格式
class People:
def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender obj=People('egon',18,'male') dir(obj) # 列表中查看到的属性全为字符串 [......,'age', 'gender', 'name']
接下来就是想办法通过字符串来操作对象的属性了,这就涉及到内置函数hasattr、getattr、setattr、delattr的使用了(Python中一切皆对象,类和对象都可以被这四个函数操作,用法一样)
class Teacher: def __init__(self,full_name): self.full_name =full_name t=Teacher('Egon Lin') # hasattr(object,'name') hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name # getattr(object, 'name', default=None) getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None # setattr(x, 'y', v) setattr(t,'age',18) # 等同于t.age=18 # delattr(x, 'y') delattr(t,'age') # 等同于del t.age
基于反射可以十分灵活地操作对象的属性,比如将用户交互的结果反射到具体的功能执行
>>> 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...
二、内置方法
Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类,这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发,我们以常用的str和del为例来简单介绍它们的使用。
str方法会在对象被打印时自动触发,print功能打印的就是它的返回值,我们通常基于方法来定制对象的打印信息,该方法必须返回字符串类型
>>> class People: ... def __init__(self,name,age): ... self.name=name ... self.age=age ... def __str__(self): ... return '<Name:%s Age:%s>' %(self.name,self.age) #返回类型必须是字符串 ... >>> p=People('lili',18) >>> print(p) #触发p.__str__(),拿到返回值后进行打印 <Name:lili Age:18>
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__()
class Student: school = 'SH' def __init__(self, name): self.name = name def func(self): return self.name class Teacher(Student): def __init__(self, name, age): # super(Student, self).__init__(name) # python2中 super().__init__(name) # python3中 self.age = age def __str__(self): return self.name # 只能是字符串 def __del__(self): print('deeeee') # 删除后输出内容 def __getattr__(self, item): print('访问属性不存在输出') def __setattr__(self, key, value): # self.key = value # 会无限递归 self.__dict__[key] = value print('设置值的时候输出,如果初始化中有自动设值也执行,递归深度一般为1000') def __call__(self, *args, **kwargs): print('对象加()调用时执行') """ gte 小于等于 lte 小于等于 """ obj = Teacher('cx', 18) # del obj print(obj.__dict__) obj() """ NameError SyntaxError AttributeError KeyError TypeError ZeroDivisionError """ try: print('a') # 要检测的代码 except KeyError as e1: print('Key') except NameError as e2: print() except TypeError as e3: print() except Exception as e: print('其他所有错误在这被捕捉并执行下面代码') else: print('没有错误则执行') # else以及以上的代码只会执行一种 finally: print('不管有没有异常都会执行的代码') l = [1, 2, 3] if len(l) <5: raise Exception('断言失败') # 抛出异常: raise Execption/TypeErroe assert len(l) == 3 # 当l长度为3是抛出异常
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/245461.html