我在Python中有一个简单的mixin结构。代码应该是非常自我解释的:
class Base:
def __init__(self):
pass
class MixinA:
def __init__(self):
self.x = 0
self.y = 1
def a(self):
print('A: x = ' + str(self.x) + ', y = ' + str(self.y))
class MixinB:
def __init__(self):
self.x = 2
self.z = 3
def b(self):
print('B: x = ' + str(self.x) + ', z = ' + str(self.z))
class MyFirstMix(MixinA, MixinB, Base):
def __init__(self):
Base.__init__(self)
MixinB.__init__(self)
MixinA.__init__(self)
class MySecondMix(MixinA, Base):
def __init__(self):
Base.__init__(self)
MixinA.__init__(self)
我想稍微提高一点,所以这会导致3个问题:
MixinA
和MixinB
都有成员x
。有没有办法确保,每个班级只看到自己的x ?
据我所知:不,没有。mix = Base() with MixinA
如果我提出的结构完全错误,我也会就如何处理mixin提出其他建议。
答案 0 :(得分:0)
当您的继承方案开始遭受这些问题时,现在应该考虑使用一种名为 composition 的技术。对主题here的可读性很好的介绍。 Wikipedia example稍微不易访问,但如果您可以处理其他编程语言也很有用。 This StackExchange question也提供了有用的讨论。
最简单的,而不是继承自SomeParent
并在Mixin
类中混合的类,而是让SomeParent
个实例分别创建Mixin
的实例,用它来访问mixin类的功能。
答案 1 :(得分:0)
对于固有的python类,我相信你需要知道一些技巧:
python2和python3中的类是完全不同的。
Python2支持旧式类,但python3仅支持新式类。简单来说:在python3中,类总是来自基类object
,即使你没有明确地使用它。查看Difference-between-Old-New-Class。
方法解析订单(MRO)。这决定了派生类如何搜索固有成员和函数。请参阅MRO
super
功能。结合MRO,您可以轻松调用父成员或函数,而无需明确知道父类的名称。请参阅Super
现在提出问题:
我不会理解你的意思。引用类成员时,必须通过其实例或类引用它。因此instance_of_MixinA.x
和instance_of_MixinB.x
是分开的。如果您正在讨论类MyFirstMix(MixinA, MixinB, Base)
,那么它取决于如何调用__init__
函数。在您的代码中,首先按x
填充MixinB
,然后按MixinA
重置其值。
你的名字让它变得不可能。你必须调用所有构造函数。
我不确定。但是我可以给你一些建议:在def class(python3,如果你使用python2处理__init__
)时尝试在super
成员之外:
class Base:
def __init__(self):
pass
class MixinA:
x = 0
y = 1
class MixinB:
x = 2
z = 3
def b(self):
print('B: x = ' + str(self.x) + ', z = ' + str(self.z))
class MyFirstMix(MixinA, MixinB, Base):
def __init__(self):
super().__init__()
class MySecondMix(MixinA, Base):
def __init__(self):
super().__init__()
__init__
之外的变量与内部变量的行为不同:外部变量属于类,将为此类的所有实例填充,而内部变量仅属于实例(由self
引用时你定义了类),只有在调用__init__
时才会填充。这就是为什么你不能使用super
来调用所有构造函数--- super
只调用优先级父__init__
的原因。见variables-outsite-inside-init
这是Mixin类的一个很好的解决方案。在上面的代码中,MyFirstMix
同时包含MixinA
和MixinB
,其成员都是类成员(__init__
之外)。因此MyFirstMix
的实例将固有MixinA
和MixinB
的所有班级成员,而不会调用__init__
。此处MixinA
和MixinB
拥有相同的班级成员x
,但MRO
确定MyFirstMix
的实例引用x
,{{1}应该返回x
。
希望这会有所帮助。谢谢!