# python 反射、内置方法

目录：

* 反射
* 内置方法
* 视频链接

### 一 反射

![](https://pic2.zhimg.com/80/v2-3d1d85b30d01da04b681d316cb460975_720w.jpg)

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__()
```
