python - 装饰类方法以构建方法注册表

标签 python python-2.7 class decorator python-decorators

我想要实现的目标:

我想装饰类方法定义,以便该类可以构建某些方法的注册表。其目的如下:

class NForm(FormFiller):
    @fills('name')
    def get_name(self):
        return 'gets name'

class NAForm(NForm):
    @fills('address')
    def get_address(self):
        return 'gets address'

class NBForm(NForm):
    @fills('birthday')
    def get_birthday(self):
        return 'gets birthday'

na = NAForm().filled_form() == {'address': 'gets address',
                                'name': 'gets name'}

nb = NBForm().filled_form() == {'birthday': 'gets birthday',
                                'name': 'gets name'}

我尝试了什么

看起来很简单,所以我为父类编写了这段代码。

class FormFiller(object):
    _fills = {}

    @classmethod
    def fills(cls, field_name):
        def wrapper(func):
            cls._fills[field_name] = func.__name__
            return func
        return wrapper

    def filled_form(self):
        return {field_name: getattr(self, func)() for field_name, func in self._fills.items()}

并将上面的装饰器替换为例如@NAForm.fills('地址')。然而,这当然是不可能的,因为 NAForm 尚未在其自己的定义中定义。我只能写入任何 parent 的 _fills 属性。

感觉所需的用例应该是可能的,但我目前不知道如何实现这一点。如果我想手动实现上述行为,我可以为每个继承添加一个中间类,例如

class FormFiller(object):
    _fills = {}
    @classmethod
    def fills(cls, field_name):
        print 'in', cls, 'adding', field_name
        def wrapper(func):
            # make a copy since _fills is like a mutable default
            cls._fills = dict(cls._fills)
            # update
            cls._fills[field_name] = func.__name__
            return func
        return wrapper

    def filled_form(self):
        return {field_name: getattr(self, func)() for field_name, func in self._fills.items()}


class NFormBase(FormFiller):
    pass

class NForm(NFormBase):
    @NFormBase.fills('name')
    def get_name(self):
        return 'gets name'

class NAFormBase(NForm):
    pass

class NAForm(NAFormBase):
    @NAFormBase.fills('address')
    def get_address(self):
        return 'gets address'

class NBFormBase(NForm):
    pass

class NBForm(NBFormBase):
    @NBFormBase.fills('birthday')
    def get_age(self):
        return 'gets birthday'


print FormFiller().filled_form()  # == {}
print NForm().filled_form()  # == {'name': 'gets name'}
print NAForm().filled_form()  # == {'name': 'gets name', 'address': 'gets address'}
print NBForm().filled_form()  # == {'birthday': 'gets birthday', 'name': 'gets name'}

这似乎可行,但是a)要求您为每个继承步骤添加一个中间类,b)比必要的更频繁地复制_fills字典(在每个装饰上而不是每个类创建一次)。

有更好的方法吗?如果有任何正确方向的指示,我将不胜感激。元类是我正在寻找的吗?

谢谢!

最佳答案

事实证明元类正是我所需要的,我以前从未使用过它们,我只是在 SO 上找到了适当的问题:Auto-register class methods using decorator

registry = {}

class RegisteringType(type):
    def __init__(cls, name, bases, attrs):
        registry[name] = {}

        for base in bases:
            registry[name].update(**registry.get(base.__name__, {}))

        for key, val in attrs.iteritems():
            properties = getattr(val, 'register', None)
            if properties is not None:
                registry[name][key] = properties

def register(*args):
    def decorator(f):
        f.register = tuple(args)
        return f
    return decorator

class FormFiller(object):
    __metaclass__ = RegisteringType

    def filled_form(self):
        print type(self).__name__
        return registry[type(self).__name__]

class NForm(FormFiller):
    @register('name')
    def get_name(self):
        return 'gets name'

class NAForm(NForm):
    @register('address')
    def get_address(self):
        return 'gets address'

class NBForm(NForm):
    @register('birthday')
    def get_age(self):
        return 'gets birthday'

关于python - 装饰类方法以构建方法注册表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48709145/

相关文章:

for 循环中的 Python 变量返回 TypeError

python - 使用 Python 2.7.3 在 64 位 Windows 7 上安装 Numpy

Python 类方法在调用另一个方法时运行

python - 在 Python : "" or None? 中初始化一个字符串变量

python - 在python中将mac路径转换为posix

Python Tkinter - 如何将一个类中的小部件放到另一个类中的窗口上

python - 向类添加属性的更多 Pythonic 方式?

linux - 如何告诉 rpm 查看特定目录的依赖项?

java - 类方法未执行正确的计算

c++ - 如何使用 Eigen 库定义动态矩阵?