反射、内置方法

一. 反射

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')
print(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')
# hasattr(object,'name')
print(hasattr(t,'full_name')) # 按字符串'full_name'判断有无属性t.full_name
#Ture

# getattr(object, 'name', default=None)
print(getattr(t,'full_name',None))  # 等同于t.full_name,不存在该属性则返回默认值None
#egon

# setattr(x, 'y', v)
setattr(t,'age',18)
print(getattr(t,'age',None))  # 等同于t.age=18
#

# delattr(x, 'y')
delattr(t,'age')
print(getattr(t,'age',None))  # 等同于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):
               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 b.txt
#>>> Uploading b.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__()