Python 反射机制

Python 反射机制是一种在运行时检查、访问和修改对象属性和方法的能力。下面介绍下相关的模块和函数:

  1. 内置函数
  2. inspect 模块
  3. 插件系统示例

1. 内置函数

  1. getattr(obj, name[, default]): 获取对象 obj 的属性或方法 name 的值;
  2. hasattr(obj, name): 检查对象 obj 是否具有属性或方法 name。返回布尔值;
  3. setattr(obj, name, value): 设置对象 obj 的属性或方法 name 的值为 value
  4. delattr(obj, name): 删除对象 obj 的属性或方法 name
  5. dir(obj): 返回对象 obj 的所有属性和方法的名称列表。

2. inspect 模块

  1. inspect.getmembers(object[, predicate]):用于获取对象 object 中的所有属性和方法;
  2. inspect.ismodule(object):检查对象是否是一个模块;
  3. inspect.isclass(object):检查对象是否是一个类;
  4. inspect.isfunction(object):检查对象是否是一个函数;
  5. inspect.ismethod(object):检查对象是否是一个方法;
  6. inspect.isbuiltin(object):检查对象是否是一个内置函数或方法;
  7. inspect.isroutine(object):检查对象是否是函数、方法或内置函数;
  8. inspect.getmodule(object):返回定义对象的模块。如果对象没有模块信息,则返回 None
  9. inspect.getsource(object):获取对象的源代码,如果源代码不可用则引发 OSError 异常;
  10. inspect.getfile(object):获取对象所属模块的文件名;
  11. inspect.getmembers(object):获取对象的属性和方法列表;
  12. inspect.getdoc(object):获取对象的文档字符串;
  13. inspect.signature(object):返回一个 Signature 对象,该对象包含了函数或方法的参数信息;
  14. inspect.getclasstree(classes[, unique]):返回一个树形结构,表示一组类之间的继承关系;
  15. inspect.getmro(cls):返回一个元组,包含类 cls 及其基类的方法解析顺序;
  16. inspect.getframeinfo(frame, context=1):返回包含帧对象信息的命名元组,用于分析调用堆栈;
  17. inspect.currentframe():获取当前帧对象,可用于分析调用堆栈。

3. 插件系统示例

文件架构如下。当我们在 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()
未经允许不得转载:一亩三分地 » Python 反射机制
评论 (0)

6 + 6 =