moo*_*nts 4 python class mixins
我想要一个基于传递给构造函数的参数添加mixins的类.这就是我尝试过的:
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
Run Code Online (Sandbox Code Playgroud)
唯一的问题似乎是__init__没有被调用,所以print_name方法不起作用.
__init__就Sub火?要么
这是使用元类的一个巧妙的地方.您可以将自定义mixin-inclusion代码放在meta中,然后您的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
Run Code Online (Sandbox Code Playgroud)
现在您可以创建Sub对象并指定mixin,如下所示:
>>> s = Sub('foo', mixin=MixinOne)
>>> s.print_name()
foo is using MixinOne.
Run Code Online (Sandbox Code Playgroud)
它将自动从kwargs dict中撤出,因此该__init__方法可以完全不知道它的存在.
注意:在Python 3中,mixin声明语法发生了变化:
class Sub(metaclass = AutoMixinMeta):
def __init__(self, name):
self.name = name
Run Code Online (Sandbox Code Playgroud)
__init__仅当__new__返回类的实例时才被调用。您的即时类继承自 mixin 和Sub的Parents,但不继承自Sub其自身。如果你设置它可能会起作用bases = (MixinOne, cls)。
编写工厂函数(或类方法)而不是重载的Sub构造。更好的是,只需创建一些子类,而不是在运行时创建类。:)
| 归档时间: |
|
| 查看次数: |
1082 次 |
| 最近记录: |