在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 First
、Second
、Third
和Fourth
的所有属性和方法都可用在 class Fourth
中。
现在,我希望 class Fourth
根据上下文有选择地从 parents 继承 - 即,单独从 First
或从 First
和 Third
等。一种方法是将单独的 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)
继承First
和Third
?
可以通过__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 的对象将具有不同的行为。这会打扰未来的读者和维护者
我定义了以下 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 First
、Second
、Third
和Fourth
的所有属性和方法都可用在 class Fourth
中。
现在,我希望 class Fourth
根据上下文有选择地从 parents 继承 - 即,单独从 First
或从 First
和 Third
等。一种方法是将单独的 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)
继承First
和Third
?
可以通过__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 的对象将具有不同的行为。这会打扰未来的读者和维护者