python - 用于保存有关类的元数据的装饰器替代品

标签 python python-3.x decorator

我正在编写一个 GUI 库,我想让程序员提供关于他们的程序的元信息,我可以用它来微调 GUI。我打算为此目的使用函数装饰器,例如:

class App:
    @Useraction(description='close the program', hotkey='ctrl+q')
    def quit(self):
        sys.exit()

问题是此信息需要绑定(bind)到相应的类。例如,如果程序是一个图像编辑器,它可能有一个 Image 类,它提供了更多的用户操作:

class Image:
    @Useraction(description='invert the colors')
    def invert_colors(self):
        ...

但是,由于未绑定(bind)方法的概念已在 python 3 中删除,因此似乎没有办法找到函数的定义类。 (我找到了 this old answer ,但这在装饰器中不起作用。)

那么,既然装饰器看起来行不通,那么最好的方法是什么?我想避免像这样的代码

class App:
    def quit(self):
        sys.exit()

Useraction(App.quit, description='close the program', hotkey='ctrl+q')

如果可能的话。


为了完整起见,@Useraction 装饰器看起来有点像这样:

class_metadata= defaultdict(dict)
def Useraction(**meta):
    def wrap(f):
        cls= get_defining_class(f)
        class_metadata[cls][f]= meta
        return f
    return wrap

最佳答案

您正在使用装饰器将元数据添加到方法中。没事儿。可以做到,例如这样:

def user_action(description):
    def decorate(func):
        func.user_action = {'description': description}
        return func
    return decorate

现在,您想要收集该数据并将其以 class_metadata[cls][f]= meta 的形式存储在全局字典中。为此,您需要找到所有修饰的方法及其类。

最简单的方法可能是使用元类。在元类中,您可以定义创建类时发生的情况。在这种情况下,遍历类的所有方法,找到装饰方法并将它们存储在字典中:

class UserActionMeta(type):
    user_action_meta_data = collections.defaultdict(dict)

    def __new__(cls, name, bases, attrs):
        rtn = type.__new__(cls, name, bases, attrs)
        for attr in attrs.values():
            if hasattr(attr, 'user_action'):
                UserActionMeta.user_action_meta_data[rtn][attr] = attr.user_action
        return rtn

我将全局字典 user_action_meta_data 放在元类中只是因为它感觉合乎逻辑。它可以在任何地方。

现在,只需在任何类中使用它:

class X(metaclass=UserActionMeta):

    @user_action('Exit the application')
    def exit(self):
        pass

静态 UserActionMeta.user_action_meta_data 现在包含您想要的数据:

defaultdict(<class 'dict'>, {<class '__main__.X'>: {<function exit at 0x00000000029F36C8>: {'description': 'Exit the application'}}})

关于python - 用于保存有关类的元数据的装饰器替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42322828/

相关文章:

python - 在圆 OpenCV 内绘制文本

python - 打印一系列文本中最长的一行以及字符数

python - 以反射方式在 Python 中创建嵌套类

module - 如何从特定模块创建所有装饰函数的向量?

python - 在 python 的 100 x 100 矩阵中,填充非对角线元素

python - 如何循环遍历 pandas 数据框并在条件下修改值?

angular - 为什么 Angular 2 使用装饰器?

python 类方法的装饰器

python - 为什么我的环境变量无法加载到我的 Flask 应用程序中?

python - 添加计数器作为数据帧的索引