簡體   English   中英

如何在實例化時有條件地將 mixin 添加到當前類?

[英]How can I conditionally add in a mixin to the current class on instantiation?

我想要一個類,它根據傳遞給構造函數的參數添加混入。 這是我嘗試過的:

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. 如何讓Sub上的__init__觸發?

或者

  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(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 中發生了變化:

class Sub(metaclass = AutoMixinMeta):
    def __init__(self, name):
    self.name = name
  1. __init__僅在__new__返回類的實例時調用。 您的動態類從 mixin 和Subparents繼承,但不是從Sub本身繼承。 如果您設置bases = (MixinOne, cls)它可能會起作用。

  2. 編寫工廠函數(或類方法)而不是重載Sub的構造。 更好的是,只需創建一些子類,而不是在運行時創建類。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM