Python-涉及多重继承时调用祖先方法 [英] Python - calling ancestor methods when multiple inheritance is involved

查看:215
本文介绍了Python-涉及多重继承时调用祖先方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Python 3(有人问).

I'm using Python 3 (some people asked).

我认为这只是一个语法问题,但是我想确保没有任何我想念的东西.注意在实现Foo和Bar方面的语法差异.他们实现了同一件事,我想确保他们确实在做同一件事.输出表明只有两种方法可以完成相同的操作.是这样吗?

I think this is just a syntax question, but I want to be sure there's nothing I'm missing. Notice the syntax difference in how Foo and Bar are implemented. They achieve the same thing and I want to make sure they're really doing the same thing. The output suggests that there are just two ways to do the same thing. Is that the case?

代码:

class X:

    def some_method(self):
        print("X.some_method called")

class Y:

    def some_method(self):
        print("Y.some_method called")

class Foo(X,Y):

    def some_method(self):
        X().some_method()
        Y().some_method()
        print("Foo.some_method called")

class Bar(X,Y):

    def some_method(self):
        X.some_method(self)
        Y.some_method(self)
        print("Bar.some_method called")

print("=== Fun with Foo ===")
foo_instance = Foo()
foo_instance.some_method()

print("=== Fun with Bar ===")
bar_instance = Bar()
bar_instance.some_method()

输出:

=== Fun with Foo ===
X.some_method called
Y.some_method called
Foo.some_method called
=== Fun with Bar ===
X.some_method called
Y.some_method called
Bar.some_method called

PS-希望不用说,但这只是一个抽象的例子,我们不必担心为什么我想在两个祖先上都使用some_method,我我只是想在这里理解该语言的语法和机制.谢谢大家!

PS - Hopefully it goes without saying but this is just an abstract example, let's not worry about why I'd want to call some_method on both ancestors, I'm just trying to understand the syntax and mechanics of the language here. Thanks all!

推荐答案

它们是不同的. X()创建类X的对象.当您执行X().someMethod()时,将创建一个新对象,然后在该对象上而不是在self上调用该方法. X.someMethod(self)是您想要的,因为它会在同一个对象上调用继承的方法.

They aren't the same. X() creates an object of class X. When you do X().someMethod() you create a new object and then call the method on that object, not on self. X.someMethod(self) is what you want, since that calls the inherited method on the same object.

如果您的方法实际上对self对象执行任何操作,则将看到差异.例如,如果将self.blah = 8放入方法中,则在X.someMethod(self)之后,调用它的对象将设置blah属性,但在X().someMethod()之后将没有设置. (相反,您将创建一个新对象,在该对象上设置blah,然后不使用该新对象就将其丢弃,而保持原始对象不变.)

You will see the difference if your method actually does anything to the self object. For instance, if you put self.blah = 8 into your method, then after X.someMethod(self) the object you call it on will have the blah attribute set, but after X().someMethod() it will not. (Instead, you will have created a new object, set blah on that, and then thrown away that new object without using it, leaving the original object untouched.)

这是修改代码的简单示例:

Here is a simple example modifying your code:

>>> class X:
... 
...     def some_method(self):
...         print("X.some_method called on", self)
... 
... class Y:
... 
...     def some_method(self):
...         print("Y.some_method called on", self)
... 
... class Foo(X,Y):
... 
...     def some_method(self):
...         X().some_method()
...         Y().some_method()
...         print("Foo.some_method called on", self)
... 
... class Bar(X,Y):
... 
...     def some_method(self):
...         X.some_method(self)
...         Y.some_method(self)
...         print("Bar.some_method called on", self)
>>> Foo().some_method()
('X.some_method called on', <__main__.X instance at 0x0142F3C8>)
('Y.some_method called on', <__main__.Y instance at 0x0142F3C8>)
('Foo.some_method called on', <__main__.Foo instance at 0x0142F3A0>)
>>> Bar().some_method()
('X.some_method called on', <__main__.Bar instance at 0x0142F3C8>)
('Y.some_method called on', <__main__.Bar instance at 0x0142F3C8>)
('Bar.some_method called on', <__main__.Bar instance at 0x0142F3C8>)

请注意,当我使用Foo时,打印的对象是不同的.一个是X实例,一个是Y实例,最后一个是我在其上调用方法的原始Foo实例.使用Bar时,它是每个方法调用中的同一对象.

Note that when I use Foo, the objects printed are not the same; one is an X instance, one is a Y instance, and the last is the original Foo instance that I called the method on. When Bar is used, it is the same object in each method call.

(在某些情况下,也可以使用super以避免显式命名基类;例如,super(Foo, self).someMethod()或在Python 3中只是super().someMethod().但是,如果需要直接从两个调用继承的方法,基类,super可能不是一个很好的选择,它通常针对每个方法仅调用一次super并将控制权传递给继承链中方法的下一版本的情况,然后将其传递给下一个,等等)

(You can also use super in some cases to avoid naming the base classes explicitly; e.g., super(Foo, self).someMethod() or in Python 3 just super().someMethod(). However, if you have a need to directly call inherited methods from two base classes, super might not be a good fit. It is generally aimed at cases where each method calls super just once, passing control to the next version of the method in the inheritance chain, which will then pass it along to the next, etc.)

这篇关于Python-涉及多重继承时调用祖先方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆