在childclass中选择性地继承python

Selectively inherit in a child class in python

我定义了以下 classes:

class First(object):
    def __init__(self):
        print("first")

    def mF1(self):
        print "first 1"

    def mF2(self):
        print "first 2"


class Second(object):
    def __init__(self):
        print("second")

    def mS1(self):
        print "second 1"


class Third(object):
    def __init__(self):
        print("third")

    def mT1(self):
        print "third 1"

    def mT2(self):
        print "third 2"

    def mT3(self):
        print "third 3"


class Fourth(First, Second, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print("fourth")


C = Fourth()
C.mF1()
C.mF2()
C.mS1()
C.mT1()
C.mT2()
C.mT3()

给出输出:

first
fourth
first 1
first 2
second 1
third 1
third 2
third 3

至此,很明显classes FirstSecondThirdFourth的所有属性和方法都可用在 class Fourth 中。 现在,我希望 class Fourth 根据上下文有选择地从 parents 继承 - 即,单独从 First 或从 FirstThird 等。一种方法是将单独的 classes 定义如下:

class Fourth1(First):
    def __init__(self):
        super(Fourth, self).__init__()
        print("fourth first")


class Fourth2(First, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print("fourth first third")

这意味着定义了单独的 class 并且具有单独的 class 名称而不是一个。

我想知道是否有更简单、动态且 "pythonic" 的方法来实现此目的?是否可以选择继承的位置(就像 super() 一样,继承所有属性和方法,包括私有方法),比如

C = Fourth(1,0,0)

继承自First

C = Fourth(1,0,1)

继承FirstThird?

可以通过__new__完成。因为可以动态创建继承自其他 classes 的 classes,并且 __new__ 可以创建任意类型的对象:

class Fourth(object):
    """BEWARE special class that creates objects of subclasses"""
    classes = [None] * 8

    def __new__(cls, first, second, third):
        index = 1 if first else 0
        index += 2 if second else 0
        index += 4 if third else 0
        if not cls.classes[index]:
            parents = [Fourth]
            if first: parents.append(First)
            if second: parents.append(Second)
            if third: parents.append(Third)
            ns = {'__new__': object.__new__,
                  '__init__': Fourth._child__init__,
                  '__doc__': Fourth.__doc__}
            cls.classes[index] = type('Fourth', tuple(parents), ns)
        return object.__new__(cls.classes[index])

    def _child__init__(self, first = None, second=None, third=None):
        Fourth.__init__(self)

    def __init__(self):
        print("Fourth")

之后你可以做你想做的事了:

>>> c = Fourth(1,0,0)
Fourth
>>> c2 = Fourth(1,1,1)
Fourth
>>> c
<__main__.Fourth1 object at 0x0000024026151780>
>>> c2
<__main__.Fourth7 object at 0x000002402616E8D0>
>>> c2.mT1()
third 1
>>> c.mT1()
Traceback (most recent call last):
  File "<pyshell#302>", line 1, in <module>
    c.mT1()
AttributeError: 'Fourth1' object has no attribute 'mT1'

但我强烈建议您不要进行这种黑客攻击,除非您有重要的理由这样做。因为它以 class (Fourth) 结束,它不是从自身而是从子 classes 创建对象。显然属于 class 的对象将具有不同的行为。这会打扰未来的读者和维护者