Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 向继承mixin类的类动态添加类变量_Python_Python 3.x - Fatal编程技术网

Python 向继承mixin类的类动态添加类变量

Python 向继承mixin类的类动态添加类变量,python,python-3.x,Python,Python 3.x,我有一个mixin类,它为继承类添加了一些功能,但是mixin需要一些类属性,为了简单起见,让我们假设只有一个属性处理程序。这就是mixin的用法: class Mixin: pass class Something(Mixin): handlers = {} 没有定义它,mixin就无法运行,但是我真的不想在我想要使用mixin的每个类中指定处理程序。所以我写了一个元类来解决这个问题: class MixinMeta: def __new__(mcs, *args,

我有一个mixin类,它为继承类添加了一些功能,但是mixin需要一些类属性,为了简单起见,让我们假设只有一个属性
处理程序
。这就是mixin的用法:

class Mixin:
    pass

class Something(Mixin):
    handlers = {}
没有定义它,mixin就无法运行,但是我真的不想在我想要使用mixin的每个类中指定
处理程序。所以我写了一个元类来解决这个问题:

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

class Mixin(metaclass=MixinMeta):
    pass
class Mixin:
    def __new__(cls):
         if not hasattr(cls, handlers):
              cls.handlers = {}
         return super().__new__(cls)
这正是我想要的。但我认为这可能会成为一个巨大的问题,因为元类不能很好地协同工作(我读到各种元类冲突只能通过创建一个解决这些冲突的新元类来解决)

另外,我不想让
handlers
属性成为
Mixin
类本身的属性,因为这意味着必须在
Mixin
类中按类名称存储处理程序,这会使代码复杂化一点。我喜欢让每个类在自己的类上都有自己的处理程序——这使使用它们变得更简单,但显然这有缺点


我的问题是,有什么更好的方法来实现这一点?我对元类相当陌生,但它们似乎很好地解决了这个问题。但是,在处理复杂的层次结构时,元类冲突显然是一个巨大的问题,而不必定义各种元类来解决这些冲突。

您的问题是非常真实的,Python人员已经在Python 3.6(尚未实现)中考虑到了这一点。目前(直到Python 3.5),如果您的属性可以等到类第一次实例化后才存在,那么您可以将cod放在mixin类本身的
\uuuuuuu new\uuuuuuu
方法上创建(class)属性,从而避免(额外)元类:

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

class Mixin(metaclass=MixinMeta):
    pass
class Mixin:
    def __new__(cls):
         if not hasattr(cls, handlers):
              cls.handlers = {}
         return super().__new__(cls)
对于Python3.6 on,定义了一个
\uuuu init\u子类
特殊方法,用于mixin类主体。这个特殊的方法不是为mixin类本身调用的,而是在
type.\uuuuu new\uuuuu
方法(从mixin继承的每个类的“根”元类)的末尾调用的

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

根据PEP的背景文本,这一点的主要动机正是促使您提出问题的原因:当需要简单定制类创建时,避免使用元类,以减少项目中需要不同元类的机会,从而引发元类冲突的情况

“这可能成为一个巨大的问题“-如果没有呢?Python3.6将获得一个钩子,它可以让您在不使用元类的情况下做您想做的事情,但是3.6还没有出现。@jonrsharpe在最简单的情况下确实如此。我有一个元类,所有小部件都是用它来构造的。现在元类被扩展了几次,每一次都有各自的用例。现在假设我想制作一个使用这些元类和我的元类的小部件,我需要制作尽可能多的元类来处理冲突,就像为一个额外的元类创建其他类一样。这对我来说似乎不可行。@user2357112不幸的是,我使用的是Python 3.4,所以这对我来说不是一个选项。非常感谢,我一定会尝试
\uuuu new\uu
解决方案!我感谢您的帮助,不幸的是,您的解决方案没有起作用,因为我必须在实例化任何类之前访问这些属性。我最终解决了这个问题,创建了一个描述符来在基本Mixin类上创建处理程序的中心注册表。虽然不理想,但它确实有效。不管怎样,非常感谢!