繁体   English   中英

在创建时将属性附加到类

[英]Attaching attributes to a class on creation

我有一堆在ZODB中持久化的类。 所有类都必须共享一些索引功能,但它们都定义了很多属性。 这些属性在类级别上使用描述符定义,以便能够拦截写入它们以进行验证并检查数据库中的重复项。 为此,每个类都有一个自动维护的属性列表_properties 它们还_indices和其他一些功能,我不想将它们自己复制到每个Element-class(大约10个左右)。

请考虑以下代码:

class BaseElement(object):
    _properties = None

class ElementFlavour1(BaseElement):
    _properties = 'a', 'b', 'c'

....

class ElementFlavourN(BaseElement):
    _properties = 'e', 'f', 'g'

for item in locals():
    if issubclass(item, BaseElement):
        item._v_properties_set = set(item._properties) if item._properties else set()

所以,它基本上做它应该做的事情:我需要线性迭代_properties ,但我也想快速查找,如果类中存在某些属性。 不过,我不想重复自己,并明确地为每一种BaseElement指定这个集合。

目前的解决方案是有效的,但我认为这是一个丑陋的黑客,并希望摆脱它。 例如,其他模块中的BaseElement子类不会使其属性设置正确。 使用__new__也似乎是错误的方式,因为它不拦截类构造,而是实例化。 那么,如何正确地做到这一点?

PS我知道OrderedDict,但这不是我想要的。 我想以干净的方式挂钩类创建过程并在那里附加任意功能。

您可以使用元类执行此操作:

class BaseType(type):
    def __init__(cls, name, bases, clsdict):
        super(BaseType, cls).__init__(name, bases, clsdict)
        setattr(cls,'_v_properties_set',
                set(cls._properties) if cls._properties else set())

class BaseElement(object):
    __metaclass__ = BaseType    
    _properties = None

class ElementFlavour1(BaseElement):
    _properties = 'a', 'b', 'c'

class ElementFlavourN(BaseElement):
    _properties = 'e', 'f', 'g'

print(ElementFlavourN._v_properties_set)
# set(['e', 'g', 'f'])

您也可以使用类装饰器执行此操作,但是您必须单独装饰BaseElement每个子类。 元类是继承的,因此您只需定义一次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM