为什么可以调用超类没有的方法
Why can call a method that the superclass does not have
我正在阅读使用 Python 2.7 实现 paxos 算法的源代码。在代码中,有很多方法调用了超类的方法,而超类中并没有这个方法,而且这两个方法的名称总是相同的。这是 Python 的特殊功能吗?
例如。超级(SimpleSynchronizationStrategyMixin,自我)。set_messenger(信使)
SimpleSynchronizationStrategyMixin 的超类是不包含方法 "set_messenger" 的对象。这行代码所属的方法名也是"set_messenger"
class SimpleSynchronizationStrategyMixin(object):
sync_delay = 10.0
def set_messenger(self, messenger):
super(SimpleSynchronizationStrategyMixin,self).set_messenger(messenger)
def sync():
self.messenger.send_sync_request(random.choice(self.peers), self.instance_number)
self.sync_task = task.LoopingCall(sync)
self.sync_task.start(self.sync_delay)
def receive_sync_request(self, from_uid, instance_number):
if instance_number < self.instance_number:
self.messenger.send_catchup(from_uid, self.instance_number, self.current_value)
def receive_catchup(self, from_uid, instance_number, current_value):
if instance_number > self.instance_number:
print 'SYNCHRONIZED: ', instance_number, current_value
self.advance_instance(instance_number, current_value, catchup=True)
您发布的代码确实看起来很奇怪,单独使用此 class 确实会失败。例如,使用以下最小示例:
class SimpleSynchronizationStrategyMixin(object):
def set_messenger(self, messenger):
super(SimpleSynchronizationStrategyMixin,self).set_messenger(messenger)
print('test')
test = SimpleSynchronizationStrategyMixin()
test.set_messenger(None)
如您所料,会报错:
AttributeError: 'super' object has no attribute 'set_messenger'
然而,class的名字揭示了答案:它是一个"mixin"class,一个class本来就是与另一个 class 混在一起。因此 class 仅添加某些功能,并且可能对超级对象中存在的方法做出假设(在最终对象的情况下是 而不是 object
).
为了证明这一点,让我们用下面的代码扩展上面的例子:
class SomeOtherClass(object):
def set_messenger(self, messenger):
print('setting the messenger to %s.' % repr(messenger))
class Demo(SimpleSynchronizationStrategyMixin, SomeOtherClass):
def demo(self):
self.set_messenger('some messenger')
demo = Demo()
demo.demo()
这里,set_messenger
方法定义在SomeOtherClass
中。 Demo
class 然后使用 SomeOtherClass
和 mixin 创建最终对象。当 demo()
被调用时,它打印:
setting the messenger to 'some messenger'.
test
请注意,超级 classes 的顺序很重要。如果你写 class Demo(SomeOtherClass, SimpleSynchronizationStrategyMixin)
那么行 "test" 就不会被打印出来。
有关您的特定 paxos 示例,请参阅 server.py
,其中包含:
class ReplicatedValue(DedicatedMasterStrategyMixin, ExponentialBackoffResolutionStrategyMixin, SimpleSynchronizationStrategyMixin, BaseReplicatedValue):
"""
Mixes the dedicated master, resolution, and synchronization strategies into the base class
""
在这里你可以看到一些mixin classes是"added"到BaseReplicatedValue
来创建ReplicatedValue
.
请注意 super()
并不总是 return "parent" 对象。如果方法DedicatedMasterStrategyMixin.propose_update(self, ...)
调用了super(DedicatedMasterStrategyMixin, self).propose_update(...)
,则根据Method Resolution Order (MRO)找到下一个propose_update()
方法。简单地说,它从左到右查找所有基 classes,returns 是找到的第一个方法。这样,每个方法都可以在不知道哪个 class 是 "parent" 的情况下调用 super()
,因此仍然可以链接所有必要的方法。以下示例代码演示了这一点:
class Base(object):
def test(self):
# NB: No super() call in the base class!
print('Test Base')
print('')
class MixinX(object):
def test(self):
print('Test X')
super(MixinX, self).test()
class MixinY(object):
def test(self):
print('Test Y')
super(MixinY, self).test()
class MixinZ(object):
def test(self):
print('Test Z')
super(MixinZ, self).test()
class Final(Base):
pass
class FinalX(MixinX, Base):
pass
class FinalXYZ(MixinX, MixinY, MixinZ, Base):
pass
class FinalZYX(MixinZ, MixinY, MixinX, Base):
pass
class WrongOrder(Base, MixinX, MixinY, MixinZ):
pass
class MixinsOnly(MixinX, MixinY, MixinZ):
pass
"""
>>> Final().test()
Test Base
>>> FinalX().test()
Test X
Test Base
>>> FinalXYZ().test()
Test X
Test Y
Test Z
Test Base
>>> FinalZYX.test()
Test Z
Test Y
Test X
Test Base
>>> WrongOrder().test()
Test Base
>>> MixinsOnly().test()
Test X
Test Y
Test Z
Traceback (most recent call last):
File "superdemo.py", line 36, in <module>
MixinsOnly().test()
File "superdemo.py", line 9, in test
super(MixinX, self).test()
File "superdemo.py", line 14, in test
super(MixinY, self).test()
File "superdemo.py", line 19, in test
super(MixinZ, self).test()
AttributeError: 'super' object has no attribute 'test'
>>> FinalXYZ.mro()
[<class '__main__.FinalXYZ'>, <class '__main__.MixinX'>, <class '__main__.MixinY'>, <class '__main__.MixinZ'>, <class '__main__.Base'>, <type 'object'>]
"""
我正在阅读使用 Python 2.7 实现 paxos 算法的源代码。在代码中,有很多方法调用了超类的方法,而超类中并没有这个方法,而且这两个方法的名称总是相同的。这是 Python 的特殊功能吗? 例如。超级(SimpleSynchronizationStrategyMixin,自我)。set_messenger(信使) SimpleSynchronizationStrategyMixin 的超类是不包含方法 "set_messenger" 的对象。这行代码所属的方法名也是"set_messenger"
class SimpleSynchronizationStrategyMixin(object):
sync_delay = 10.0
def set_messenger(self, messenger):
super(SimpleSynchronizationStrategyMixin,self).set_messenger(messenger)
def sync():
self.messenger.send_sync_request(random.choice(self.peers), self.instance_number)
self.sync_task = task.LoopingCall(sync)
self.sync_task.start(self.sync_delay)
def receive_sync_request(self, from_uid, instance_number):
if instance_number < self.instance_number:
self.messenger.send_catchup(from_uid, self.instance_number, self.current_value)
def receive_catchup(self, from_uid, instance_number, current_value):
if instance_number > self.instance_number:
print 'SYNCHRONIZED: ', instance_number, current_value
self.advance_instance(instance_number, current_value, catchup=True)
您发布的代码确实看起来很奇怪,单独使用此 class 确实会失败。例如,使用以下最小示例:
class SimpleSynchronizationStrategyMixin(object):
def set_messenger(self, messenger):
super(SimpleSynchronizationStrategyMixin,self).set_messenger(messenger)
print('test')
test = SimpleSynchronizationStrategyMixin()
test.set_messenger(None)
如您所料,会报错:
AttributeError: 'super' object has no attribute 'set_messenger'
然而,class的名字揭示了答案:它是一个"mixin"class,一个class本来就是与另一个 class 混在一起。因此 class 仅添加某些功能,并且可能对超级对象中存在的方法做出假设(在最终对象的情况下是 而不是 object
).
为了证明这一点,让我们用下面的代码扩展上面的例子:
class SomeOtherClass(object):
def set_messenger(self, messenger):
print('setting the messenger to %s.' % repr(messenger))
class Demo(SimpleSynchronizationStrategyMixin, SomeOtherClass):
def demo(self):
self.set_messenger('some messenger')
demo = Demo()
demo.demo()
这里,set_messenger
方法定义在SomeOtherClass
中。 Demo
class 然后使用 SomeOtherClass
和 mixin 创建最终对象。当 demo()
被调用时,它打印:
setting the messenger to 'some messenger'.
test
请注意,超级 classes 的顺序很重要。如果你写 class Demo(SomeOtherClass, SimpleSynchronizationStrategyMixin)
那么行 "test" 就不会被打印出来。
有关您的特定 paxos 示例,请参阅 server.py
,其中包含:
class ReplicatedValue(DedicatedMasterStrategyMixin, ExponentialBackoffResolutionStrategyMixin, SimpleSynchronizationStrategyMixin, BaseReplicatedValue):
"""
Mixes the dedicated master, resolution, and synchronization strategies into the base class
""
在这里你可以看到一些mixin classes是"added"到BaseReplicatedValue
来创建ReplicatedValue
.
请注意 super()
并不总是 return "parent" 对象。如果方法DedicatedMasterStrategyMixin.propose_update(self, ...)
调用了super(DedicatedMasterStrategyMixin, self).propose_update(...)
,则根据Method Resolution Order (MRO)找到下一个propose_update()
方法。简单地说,它从左到右查找所有基 classes,returns 是找到的第一个方法。这样,每个方法都可以在不知道哪个 class 是 "parent" 的情况下调用 super()
,因此仍然可以链接所有必要的方法。以下示例代码演示了这一点:
class Base(object):
def test(self):
# NB: No super() call in the base class!
print('Test Base')
print('')
class MixinX(object):
def test(self):
print('Test X')
super(MixinX, self).test()
class MixinY(object):
def test(self):
print('Test Y')
super(MixinY, self).test()
class MixinZ(object):
def test(self):
print('Test Z')
super(MixinZ, self).test()
class Final(Base):
pass
class FinalX(MixinX, Base):
pass
class FinalXYZ(MixinX, MixinY, MixinZ, Base):
pass
class FinalZYX(MixinZ, MixinY, MixinX, Base):
pass
class WrongOrder(Base, MixinX, MixinY, MixinZ):
pass
class MixinsOnly(MixinX, MixinY, MixinZ):
pass
"""
>>> Final().test()
Test Base
>>> FinalX().test()
Test X
Test Base
>>> FinalXYZ().test()
Test X
Test Y
Test Z
Test Base
>>> FinalZYX.test()
Test Z
Test Y
Test X
Test Base
>>> WrongOrder().test()
Test Base
>>> MixinsOnly().test()
Test X
Test Y
Test Z
Traceback (most recent call last):
File "superdemo.py", line 36, in <module>
MixinsOnly().test()
File "superdemo.py", line 9, in test
super(MixinX, self).test()
File "superdemo.py", line 14, in test
super(MixinY, self).test()
File "superdemo.py", line 19, in test
super(MixinZ, self).test()
AttributeError: 'super' object has no attribute 'test'
>>> FinalXYZ.mro()
[<class '__main__.FinalXYZ'>, <class '__main__.MixinX'>, <class '__main__.MixinY'>, <class '__main__.MixinZ'>, <class '__main__.Base'>, <type 'object'>]
"""