Python 反射机制是一种在运行时检查、访问和修改对象属性和方法的能力。下面介绍下相关的模块和函数:
-
内置函数
-
inspect 模块
-
插件系统示例
-
内置函数 {#title-0} ==================
-
getattr(obj, name[, default])
: 获取对象obj
的属性或方法name
的值; -
hasattr(obj, name)
: 检查对象obj
是否具有属性或方法name
。返回布尔值; -
setattr(obj, name, value)
: 设置对象obj
的属性或方法name
的值为value
; -
delattr(obj, name)
: 删除对象obj
的属性或方法name
; -
dir(obj)
: 返回对象obj
的所有属性和方法的名称列表。 -
inspect 模块 {#title-1} ========================
-
inspect.getmembers(object[, predicate])
:用于获取对象object
中的所有属性和方法; -
inspect.ismodule(object)
:检查对象是否是一个模块; -
inspect.isclass(object)
:检查对象是否是一个类; -
inspect.isfunction(object)
:检查对象是否是一个函数; -
inspect.ismethod(object)
:检查对象是否是一个方法; -
inspect.isbuiltin(object)
:检查对象是否是一个内置函数或方法; -
inspect.isroutine(object)
:检查对象是否是函数、方法或内置函数; -
inspect.getmodule(object)
:返回定义对象的模块。如果对象没有模块信息,则返回None
; -
inspect.getsource(object)
:获取对象的源代码,如果源代码不可用则引发OSError
异常; -
inspect.getfile(object)
:获取对象所属模块的文件名; -
inspect.getmembers(object)
:获取对象的属性和方法列表; -
inspect.getdoc(object)
:获取对象的文档字符串; -
inspect.signature(object)
:返回一个Signature
对象,该对象包含了函数或方法的参数信息; -
inspect.getclasstree(classes[, unique])
:返回一个树形结构,表示一组类之间的继承关系; -
inspect.getmro(cls)
:返回一个元组,包含类cls
及其基类的方法解析顺序; -
inspect.getframeinfo(frame, context=1)
:返回包含帧对象信息的命名元组,用于分析调用堆栈; -
inspect.currentframe()
:获取当前帧对象,可用于分析调用堆栈。 -
插件系统示例 {#title-2} ====================
文件架构如下。当我们在 plugins 目录下新增模块文件,系统会自行加载模块中定义的 BasePlugin 的子类,并自动调用其相关的函数。
│ main.py
│ Plugin.py
│ PluginManager.py
│
├─plugins
│ │ PluginA.py
│ │ PluginB.py
│ │ PluginC.py
│ └─
└─
完整示例代码:https://github.com/chinacpp/PluginManager,关键代码示例如下:
import importlib
import glob
import os
import inspect
from Plugin import BasePlugin
class PluginManger:
def __init__(self):
self.plugins = []
def load_plugin(self, module_name):
# 导入模块
module = importlib.import_module(module_name)
# 获得所有满足条件类对象
def predicate(module):
if not isinstance(module, type):
return False
if not issubclass(module, BasePlugin) or module is BasePlugin:
return False
return True
classes = inspect.getmembers(module, predicate=predicate)
return classes
def load_plugins(self):
# 1. 加载模块中类对象
module_names = glob.glob('plugins/*.py')
my_classes = []
for mudule_name in module_names:
module_name, extension = os.path.splitext(mudule_name)
module_name = module_name.replace(os.path.sep, '.')
classes = self.load_plugin(module_name)
my_classes.extend(classes)
# 2. 实例化插件对象
for _, my_class in my_classes:
try:
print('-----插件', my_class.__name__, '初始化-----')
object = my_class()
self.plugins.append(object)
except Exception as error:
print('Error: 插件初始化失败,原因: ', error)
def process(self):
for plugin in self.plugins:
print('-----插件', plugin.__class__.__name__, '执行-----')
plugin.enter()
plugin.do()
plugin.exit()