将对象属性链接到类或对象的最佳实践方法

时间:2013-12-18 15:30:52

标签: python metaclass

我正在寻找一种可靠的pythonic方法,为某个类型的类属性提供对它们所连接的类的反向引用。

即。如果有类似下面的类定义,我想将SomeAttribute()引用回SomeClass类型对象。

class SomeClass(object):
    attribute = SomeAttribute()

目前我有一个实现,它在创建具有这种属性的类后依赖于手动方法调用。 (以下示例)。当前方法的问题在于,许多代码需要检查引用类是否已经在访问时已填充到属性。

一种解决方案是要求初始化类,在这种情况下,bind_attributes中的代码可以放入__init__方法中。然而,即使不需要实例,这显然也需要实例化类。我相信使用元类可以实现更好的解决方案,但我不知道使用元类的pythonic实现会是什么样的。

import inspect

class Attribute(object):
    def __init__(self, *params):
        self._params = params
        self._definition_class = None

    def bind(self, definition_class):
        self._definition_class = definition_class

    def __call__(self):
        return self._definition_class.separator.join(self._params)


class Definition(object):
    separator = ', '

    publications = Attribute('Books', 'Magazines')
    clothes = Attribute('Shoes', 'Gloves', 'Hats')

    @classmethod
    def bind_attributes(cls):
        for name, attribute in inspect.getmembers(cls, lambda m: isinstance(m, Attribute)):
            attribute.bind(cls)


>>> Definition.bind_attributes()
>>> Definition.publications()
'Books, Magazines'
>>> Definition.clothes()
'Shoes, Gloves, Hats'

1 个答案:

答案 0 :(得分:1)

您可以使用元类来完成此操作。例如:

class MyMeta(type):
    def __new__(mcls, name, bases, members):
        cls = type.__new__(mcls, name, bases, members)
        for m in members.values():
            if isinstance(m, SomeAttribute):
                m.bound_cls = cls
        return cls

现在当然有一个缺点是这个功能与类而不是属性相关联,因此您需要此功能的每个类都必须使用元类:

class SomeClass(object):
    __metaclass__ = MyMeta

    attribute = SomeAttribute()