Python中的动态子类

时间:2012-01-20 16:07:12

标签: python inheritance dynamic runtime

我正在开发的库中有许多原子类(组件/混合,并不确定要调用它们),这些都是应用程序的子类。创建此原子性使应用程序只能使用它们所需的功能,并通过多重继承来组合这些组件。

然而,有时这种原子性无法得到保证,因为某些组件可能依赖于另一种组件。例如,假设我有一个组件为对象提供图形表示,另一个组件使用此图形表示来执行一些冲突检查。第一个是纯粹的原子,但后者要求当前对象已经子类化了这个图形表示组件,因此它的方法可用。这是一个问题,因为我们必须以某种方式告诉该库的用户,为了使用某个Component,他们还必须继承另一个。我们可以使这个碰撞组件子类成为可视组件,但是如果用户也将这个可视组件子类化,那么它将无法工作,因为类不在同一级别上(不像简单的钻石关系,这是期望的),并且给出程序员难以理解的神秘元类错误。

因此,我想知道是否有任何很酷的方式,通过元类重新定义或使用类装饰器来标记这些非原子组件,当它们被子类化时,额外的依赖关系将被注入到当前对象中,如果它还没有。例如:

class AtomicComponent(object):
    pass

@depends(AtomicComponent)  # <- something like this?
class UnAtomicComponent(object):
    pass

class UserClass(UnAtomicComponent): #automatically includes AtomicComponent
    pass

class UserClass2(AtomicComponent, UnAtomicComponent): #also works without problem
    pass

有人能给我一个如何做到这一点的暗示吗?或者如果它甚至可能......

编辑: 由于元类解决方案是最好的解决方案是值得商榷的,因此我将在2天内不接受这一点。

其他解决方案可能是改进错误消息,例如,执行像UserClass2之类的操作会产生错误,说UnAtomicComponent已经扩展了此组件。然而,这会产生一个问题,即不能使用两个UnAtomicComponents,因为它们会在不同的级别上对对象进行子类化。

1 个答案:

答案 0 :(得分:3)

“元类”

这就是它们的用途!在创建类时,类参数贯穿于 例如,元类代码,您可以在其中检查基数并进行更改。

这样运行没有错误 - 尽管它不保留所需类的顺序 标有“依赖”的装饰者:

class AutoSubclass(type):
    def __new__(metacls, name, bases, dct):
        new_bases = set()
        for base in bases:
            if hasattr(base, "_depends"):
                for dependence in base._depends:
                    if not dependence in bases:
                        new_bases.add(dependence)
        bases = bases + tuple(new_bases)
        return type.__new__(metacls, name, bases, dct)



__metaclass__ = AutoSubclass

def depends(*args):
    def decorator(cls):
        cls._depends = args
        return cls
    return decorator


class AtomicComponent:
    pass

@depends(AtomicComponent)  # <- something like this?
class UnAtomicComponent:
    pass

class UserClass(UnAtomicComponent): #automatically includes AtomicComponent
    pass

class UserClass2(AtomicComponent, UnAtomicComponent): #also works without problem
    pass

(我从“对象”中删除了继承,因为我声明了一个全局__metaclass__变量。所有类仍然是新的样式类并且具有此元类。继承自对象或其他类确实覆盖全局{{1变量,并且必须声明类级__metaclass__

- 编辑 -

没有元类,要做的就是让你的类正确地从它们的依赖继承。 Tehy将不再是那种“原子”,但是,由于它们无法成为那种原子,它可能无所谓。

在下面的示例中,类C和D将是您的用户类:

__metclass__