2016-10-05 34 views
4

我有一个混合类,即增加了一些功能,以继承类,但混入需要一些类属性是存在,为简单起见,假设只有一个属性handlers。因此,这将是混入的使用:被定义动态类变量添加到类继承的混合类

class Mixin: 
    pass 

class Something(Mixin): 
    handlers = {} 

的混入不能没有这个功能,但是我真的不希望指定在每类中的handlers,我想使用与混入。所以,我解决了这个写元类:

class MixinMeta: 
    def __new__(mcs, *args, **kwargs): 
     cls = super().__new__(mcs, *args, **kwargs) 
     cls.handlers = {} 
     return cls 

class Mixin(metaclass=MixinMeta): 
    pass 

而且这个作品正是我想要它。但我认为这可能会成为一个大问题,因为元类不能很好地协同工作(我读过各种元类冲突只能通过创建一个解决这些冲突的新元类来解决)。

而且,我不想让handlers属性Mixin类本身的属性,因为这将意味着具有自己的类名来存储Mixin类的内部处理程序,有点复杂的代码。我喜欢让每个班级都有自己的班级,这使得他们更简单地工作,但显然这有缺点。

我的问题是,这将是实现这个更好的办法?我对元类相当陌生,但他们似乎很好地解决了这个问题。但是,在处理复杂的层次结构时,元类冲突显然是一个巨大的问题,无需为了解决这些冲突而定义各种元类。

+0

*“这可以成为一个巨大的问题” * - 如果它不? – jonrsharpe

+1

的Python 3.6是会得到一个['__init_subclass__'(https://www.python.org/dev/peps/pep-0487/)钩住会让你做你想做的,而不元类,但是3.6 ISN”在这里呢。 – user2357112

+0

@jonrsharpe它在最微不足道的情况下。我有一个元类,构造了所有的小部件。现在元类扩展了几次,每次都有其独立的用例。现在假设我想创建一个使用这些元类和我的元类的小部件,我需要制作尽可能多的元类来处理冲突,因为还有一些其他类仅用于一个附加的元类。这对我来说似乎不可行。 – Pavlin

回答

5

你的问题是非常真实的,和Python乡亲为Python 3.6(仍unrealsed)想到了这一点。现在(直到Python 3.5),如果你的属性可以等到存在,直到你的类首次实例化,你可以把cod创建一个属于你自己的mixin类的方法的(类)属性 - 这样就避免了(额外的)元类:

class Mixin: 
    def __new__(cls): 
     if not hasattr(cls, handlers): 
       cls.handlers = {} 
     return super().__new__(cls) 

对于Python 3.6,PEP 487定义__init_subclass__特殊的方法去对mixin类机构。这个特殊的方法不是为mixin类本身调用的,而是在每个从你的mixin继承的类的方法(“根”元类)的末尾调用。

class Mixin: 
    def __init_subclass__(cls, **kwargs): 
     cls.handlers = {} 
     return super().__init_subclass__(**kwargs) 

按照该PEP的背景文字,这样做的主要动机是什么促使你问你的问题:避免元类的需求,需要创建类的简单的定制时,为了减少项目中需要不同元类的机会,从而触发元类冲突的情况。

+0

非常感谢,我一定会尝试'__new__'解决方案! – Pavlin

+0

我很感激帮助,不幸的是您的解决方案无法正常工作,因为我必须在实例化任何类之前访问这些属性。我最终通过创建描述符来创建基于Mixin类的处理程序的中央注册表来解决问题。不理想,但它的工作原理。无论如何,非常感谢! – Pavlin