如何在实例化时有条件地将 mixin 添加到当前类中?

2024-04-12

我想要一个类,根据传递给构造函数的参数添加混合。这是我尝试过的:

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方法将不起作用。

  1. 如何得到__init__ on Sub开火?

or

  1. 有一个更好的方法吗?

这是使用元类的好地方。您可以将自定义混合包含代码放入元中,然后您的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(metaclass = AutoMixinMeta):
    def __init__(self, name):
        self.name = name

现在您可以创建Sub对象并指定 mixin,如下所示:

>>> s = Sub('foo', mixin=MixinOne)
>>> s.print_name()
foo is using MixinOne.

它会自动从 kwargs 字典中取出,所以__init__方法可以完全不知道它的存在。


注意:Python 2 中的元类声明语法略有不同:

class Sub(object):
    __metaclass__ = AutoMixinMeta

    def __init__(self, name):
    self.name = name
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在实例化时有条件地将 mixin 添加到当前类中? 的相关文章

随机推荐