如何从层次结构中的类构建标记列表

时间:2016-06-13 16:37:41

标签: python multiple-inheritance

有一个使用"标签的记录器"和其他一些虚线命名空间事件来分割事件。我的程序在各个类中实现逻辑,其中大多数都是继承的,但有些是mixins。

如何干净地拥有各种级别的继承,建立最终对象可用的项目列表,包括多继承/ mixins?重载一切并调用子类的东西有点工作(mixins除外),但有点冗长(如果我做了一些疯狂的MRO东西会更加冗长)

class Base(object):
    def tags(self):
        return ['project-base']

class DoThinger(Base):
    def tags(self):
        return super(DoThinger, self).tags() + ['thinger']

class SpecialThinger(DoThinger):
    def tags(self):
        # OK, if verbose
        return super(SpecialThinger, self).tags() + ['special-1']

class SprinklesMixin(object):
    def tags(self):
        return ['sprinkles']

class SprinkleThinger(DoThinger, SprinklesMixin):
    def tags(self):
        # would need to do some magic MRO stuff
        return super(SprinkleThinger, self).tags() + ['specialsprinkles']

print(SpecialThinger().tags())  # -> ['project-base', 'thinger', 'special-1']
print(SprinkleThinger().tags()) # -> ['project-base', 'thinger', 'specialsprinkles']
#                                          (missing 'sprinkles' ^)

理想情况下,我想做类似下面的事情,所以我不会经常重复逻辑,但我不确定...中的内容。

class Base(object):
    _tags = ['project-base']

    def tags(self):
        ... # something...
        return []

class DoThinger(Base):
    _tags = ['thinger']

class SpecialThinger(DoThinger):
    _tags = ['special-1']

class SprinklesMixin(object):
    _tags = ['sprinkles']

class SprinkleThinger(DoThinger, SprinklesMixin):
    _tags = ['specialsprinkles']

assert set(SpecialThinger().tags()) == {'project-base', 'thinger', 'special-1'}
assert set(SprinkleThinger().tags()) == {'project-base', 'thinger', 'sprinkles', 'specialsprinkles'}

1 个答案:

答案 0 :(得分:0)

这是元类的“典型”用例。 Python中的普通类创建过程使用“类型”元类:它负责创建支持多重继承的正确__mro__属性。通过扩展元类行为,我们可以使用_tags在类创建时扩展__mro__属性:

class MetaBase(type):
    def __init__(cls, name, bases, dct):
        new_tags = set()
        for ancestor in cls.__mro__:
            new_tags.update(getattr(ancestor, "_tags", set()))
        cls.tags = new_tags

class Base(metaclasMetaBase):
    _tags = ['project-base']


# In Python 2.x, the class declaration is like:
class Base(object):
    __metaclass__ = MetaBase

另一种选择是让元类在类中保存_tags的描述符,在请求时计算每个类的“tags_”。它应该起作用,但可能会产生严重的副作用。比如,这些类的实例可能不会“看到”该属性 - 只要它是通过类本身的请求:

class MetaBase(type):
    @property
    def tags(cls):
        a = set()
        for supercls in cls.__mro__:
            a.update(getattr(supercls, "_tags", set()))
        return a