Python 反射

Posted 陈彦斌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 反射相关的知识,希望对你有一定的参考价值。

一 反射

什么是反射?

  反射的概念由smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在List和面向对象方面取得了成绩。

4个可以实现反射的函数

下列方法适用于类和对象

技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 # 判断object中有没有一个name字符串对应的方法或属性
 6 class BlackMedium:
 7     feture = Ugly
 8 
 9     def __init__(self, name, addr):
10         self.name = name
11         self.addr = addr
12 
13     def sell_hourse(self):
14         print(【%s】正在卖房子 % self.name)
15 
16     def rent_hourse(self):
17         print(【%s】正在租房子 % self.name)
18 
19 
20 b1 = BlackMedium(alex, 雪峰路)  # bl.name--->b1.__dic[‘name‘]
21 print(hasattr(b1, name))  # True
hasattr(object, name)
技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 # 判断object中有没有一个name字符串对应的方法或属性
 6 class BlackMedium:
 7     feture = Ugly
 8 
 9     def __init__(self, name, addr):
10         self.name = name
11         self.addr = addr
12 
13     def sell_hourse(self):
14         print(【%s】正在卖房子 % self.name)
15 
16     def rent_hourse(self):
17         print(【%s】正在租房子 % self.name)
18 
19 
20 b1 = BlackMedium(alex, 雪峰路)  # bl.name--->b1.__dic[‘name‘]
21 print(getattr(b1, name))  # alex
getattr(object, name, default = node)
技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 # 判断object中有没有一个name字符串对应的方法或属性
 6 class BlackMedium:
 7     feture = Ugly
 8 
 9     def __init__(self, name, addr):
10         self.name = name
11         self.addr = addr
12 
13     def sell_hourse(self):
14         print(【%s】正在卖房子 % self.name)
15 
16     def rent_hourse(self):
17         print(【%s】正在租房子 % self.name)
18 
19 
20 b1 = BlackMedium(alex, 雪峰路)  # bl.name--->b1.__dic[‘name‘]
21 setattr(b1, test, 123)
22 print(b1.test)  # 123
23 print(b1.__dict__)  # {‘name‘: ‘alex‘, ‘addr‘: ‘雪峰路‘, ‘test‘: 123}
setattr(x, y, v)
技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 # 判断object中有没有一个name字符串对应的方法或属性
 6 class BlackMedium:
 7     feture = Ugly
 8 
 9     def __init__(self, name, addr):
10         self.name = name
11         self.addr = addr
12 
13     def sell_hourse(self):
14         print(【%s】正在卖房子 % self.name)
15 
16     def rent_hourse(self):
17         print(【%s】正在租房子 % self.name)
18 
19 
20 b1 = BlackMedium(alex, 雪峰路)  # bl.name--->b1.__dic[‘name‘]
21 setattr(b1, test, 123)
22 print(b1.test)  # 123
23 print(b1.__dict__)  # {‘name‘: ‘alex‘, ‘addr‘: ‘雪峰路‘, ‘test‘: 123}
24 delattr(b1, test)  # <==> del b1.test
25 print(b1.__dict__)  # {‘name‘: ‘alex‘, ‘addr‘: ‘雪峰路‘}
delattr(x, y)

反射应用示例:

技术图片
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 
4 
5 class FtpClient:
6     def __init__(self, addr):
7         print(正在连接Ftp)
8         self.addr = addr
Ftp_Client.py
技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from Ftp_Client import FtpClient
 4 
 5 f1 = FtpClient(172,16,1,10)
 6 
 7 if hasattr(f1, put):
 8     func_get = getattr(f1, put)
 9     func_get()
10 else:
11     print(其他的逻辑)
Ftp_user.py

  动态导入模块:

1 # 示例一
2 from m1.t import test1
3 m = test1  # 获得顶级模块名
4 
5 
6 # 示例二
7 import importlib
8 m = importlib.import_module(字符串)  # 定位到导入的那个模块

双下划线开头的attr方法

技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 # 注:__getattr__  调用一个不存在的对象会执行
 5 class Foo:
 6     x = 1
 7 
 8     def __init__(self, y):
 9         self.y = y
10 
11     def __getattr__(self, item):
12         print(执行__getattr__)
13 
14 
15 f1 = Foo(10)
16 print(f1.y)  # 10
17 print(f1.z)  # 执行__getattr__;None
__getattr__
技术图片
 1 # 注:__delattr__ 删除操作会执行
 2 class Foo:
 3     x = 1
 4 
 5     def __init__(self, y):
 6         self.y = y
 7 
 8     def __delattr__(self, item):
 9         print(删除__delattr__)
10 
11 
12 f1 = Foo(10)
13 del f1.y  # 删除__delattr__
14 del f1.z  # 删除变量不存在时,也会执行__delattr__;删除__delattr__
__delattr__
技术图片
 1 class Foo:
 2     x = 1
 3 
 4     def __init__(self, y):
 5         self.y = y
 6 
 7     def __setattr__(self, key, value):
 8         print(执行__setattr__)
 9         self.__dict__[key] = value
10 
11 
12 f1 = Foo(10)  # 执行__setattr__
__setattr__

 二 二次加工标准类型(包装)

  包装:Python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)。

技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 class List(list):
 6     def append(self, p_object):
 7         if type(p_object) is str:
 8             super().append(p_object)  # <==> list.append(self, p_object)
 9         else:
10             print(添加数据类型不是字符串)
11 
12     def show_midille(self):  # 求列表中间值
13         mid_index = int(len(self) / 2)
14         return self[mid_index]
15 
16 
17 l1 = List(hello world!)
18 # print(l1.show_midille())  # w
19 l1.append(123)
20 print(l1)  # [‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘, ‘ ‘, ‘w‘, ‘o‘, ‘r‘, ‘l‘, ‘d‘, ‘!‘, ‘123‘]
包装

  授权:授权是包装的一个特性,包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

实现授权的关键点就是覆盖__getattr__方法

技术图片
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 import time
 4 
 5 
 6 class openfile:
 7     def __init__(self, filename, mode=r, encoding=utf-8):
 8         # self.filename = filename
 9         self.file = open(filename, mode, encoding=encoding)
10         self.mode = mode
11         self.encoding = encoding
12 
13     def write(self, line):
14         t = time.strftime(%Y-%m-%d %X)
15         time.sleep(1)
16         self.file.write(%s %s % (t, line))
17 
18     def __getattr__(self, item):
19         # print(item, type(item))  # read <class ‘str‘>
20         # self.file.read
21         return getattr(self.file, item)
22 
23 
24 f1 = openfile(a.txt, w+)
25 # print(f1.file)
26 # print(f1.read)  # 触发__getattr__;<built-in method read of _io.TextIOWrapper object at 0x000000C2ECCAAC18>
27 # f1.seek(1)
28 # print(f1.read())
29 f1.write(cpu负载过高
)
30 f1.write(内存剩余不足
)
31 
32 # a.txt内容
33 ‘‘‘
34 2019-02-17 21:30:15 cpu负载过高
35 2019-02-17 21:30:16 内存剩余不足
36 ‘‘‘
授权示例一

 

以上是关于Python 反射的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL片段着色器不照亮场景

将 OpenGL 片段着色器设置为仅通过漫反射减少 vec4 色点的 RGB 值,而不是 alpha

反射机制

反射机制入门

反射机制入门

反射机制入门