我希望有一个基于传递给构造函数的参数添加mixin的类。这就是我尝试过的:
class MixinOne(object):
def print_name(self):
print("{} is using MixinOne.".format(self.name))
class MixinTwo(object):
def print_name(self):
print("{} is using MixinTwo.".format(self.name))
class Sub(object):
def __new__(cls, *args, **kwargs):
mixin = args[1]
if mixin == 'one':
bases = (MixinOne,) + cls.__bases__
elif mixin == 'two':
bases = (MixinTwo,) + cls.__bases__
return object.__new__(type('Sub', bases, dict(cls.__dict__)))
def __init__(self, name, mixin):
print('In Sub.__init__')
self.name = name
唯一的问题似乎是__init__
没有被调用,因此print_name
方法无效。
__init__
Sub
开火?或
答案 0 :(得分:6)
这是使用元类的一个巧妙的地方。您可以将自定义混合包含代码放在元数据中,然后您的Sub
类不需要具有样板:
class AutoMixinMeta(type):
def __call__(cls, *args, **kwargs):
try:
mixin = kwargs.pop('mixin')
name = "{}With{}".format(cls.__name__, mixin.__name__)
cls = type(name, (mixin, cls), dict(cls.__dict__))
except KeyError:
pass
return type.__call__(cls, *args, **kwargs)
class Sub(object):
__metaclass__ = AutoMixinMeta
def __init__(self, name):
self.name = name
现在您可以创建Sub
个对象并指定mixin,如下所示:
>>> s = Sub('foo', mixin=MixinOne)
>>> s.print_name()
foo is using MixinOne.
它会自动退出kwargs dict,因此__init__
方法可以完全不知道它的存在。
注意:在Python 3中,mixin声明语法发生了变化:
class Sub(metaclass = AutoMixinMeta):
def __init__(self, name):
self.name = name
答案 1 :(得分:1)
__init__
返回类的实例时,才会调用 __new__
。您的即时课程继承自mixin和Sub
父母,但不是来自Sub
本身。如果您设置bases = (MixinOne, cls)
。
编写工厂函数(或classmethod),而不是重载Sub
的构造。更好的是,只需创建一些子类,而不是在运行时创建类。 :)