Python中的继承:派生类是否在基类中“复制”或“引用”方法?

Python中的继承:派生类是否在基类中“复制”或“引用”方法?,python,oop,inheritance,Python,Oop,Inheritance,在Python中执行以下代码将打印True和False 我理解为什么第一个print语句的结果是True,它的计算结果是print 42是42,但不理解为什么第二个语句的结果是False 据报道, 如果在类中找不到请求的属性,则搜索 继续查找基类 这表示在这种情况下,属性func只有一个副本,派生类只引用基类中的副本。因此,我希望foo的func与foo2的func相同 我还曾经将代码的执行可视化。它显示仅创建了一个func: 有人能解释为什么foo.func不是foo2.func吗 PS:被问

在Python中执行以下代码将打印True和False

我理解为什么第一个print语句的结果是True,它的计算结果是print 42是42,但不理解为什么第二个语句的结果是False

据报道,

如果在类中找不到请求的属性,则搜索 继续查找基类

这表示在这种情况下,属性func只有一个副本,派生类只引用基类中的副本。因此,我希望foo的func与foo2的func相同

我还曾经将代码的执行可视化。它显示仅创建了一个func:

有人能解释为什么foo.func不是foo2.func吗

PS:被问及Java,答案是派生类将引用基类中的方法。

因为foo和foo2是类和子类的两个不同实例。尽管func实际上是Foo和Foo2之间的同一引用,但一旦实例化类,绑定方法将基于这两个不同的实例创建,因此内存地址不再相同,也不再是相同的对象,即使它们执行完全相同的操作:

>>> foo = Foo()             
>>> foo2 = Foo2()               
>>> foo.func

<bound method Foo.func of <__main__.Foo object at 0x072623D0>>
>>> foo2.func

<bound method Foo.func of <__main__.Foo2 object at 0x07262AD0>>  # notice the different object
然后,如果您向Foo添加新方法,Foo2也会自动将其拾取:

>>> Foo.func2 = lambda: print('hey!')

>>> Foo2.func2

<function <lambda> at 0x0726B7C8>

因为函数是描述符,在属性查找时创建绑定方法。请尝试打印Foo.func is Foo2.func查看reprfoo.func和reprfoo2.func。他们是不同的…在attr的例子中,你只是在做42是42,这是真的,但不是很有趣。在func案例中,您正在比较两个绑定方法。这些都是自我约束的方法。在一种情况下,self是foo,而在另一种情况下self是foo2。所以它们不一样,事实上,如果func对self做了一些操作,调用它们时可能会有不同的行为。@Phydeaux在Python2 Foo.func中不是Foo2.func,而在Python3中Foo.func是Foo2.func。这个答案只适用于Python3。对于Python2,即使两个实例属于同一类,foo2.func也将是相同的,一个实例的方法与另一个实例的相应方法具有不同的地址。>>>a=Foo>>>>b=Foo>>>a.func>>>b.func我不明白你想说什么。。。我的意思是,绑定方法在每个实例中都是独立的,不管类是什么,你同意吗?是的,我只是想添加另一个实例:同一个类的两个实例,而不是基类的一个实例和派生类的一个实例。
>>> Foo2.func

<function Foo.func at 0x0726B780>
>>> Foo.func

<function Foo.func at 0x0726B780>
>>> Foo.func = lambda: print("I'm new!")

>>> Foo.func

<function <lambda> at 0x0726B738>
>>> Foo2.func

<function <lambda> at 0x0726B738>  # Follows the same reference
>>> Foo2.func = lambda: print("Some other func")

>>> Foo2.func

<function <lambda> at 0x0726B780>  # New function
>>> Foo.func

<function <lambda> at 0x0726B738>  # unchanged.
>>> Foo.func2 = lambda: print('hey!')

>>> Foo2.func2

<function <lambda> at 0x0726B7C8>
>>> Foo.func = lambda: print("I'm renewed!")

>>> Foo.func

<function <lambda> at 0x0726B738>  # newly assigned object
>>> Foo2.func

<function <lambda> at 0x0726B780>  # Reference remains as before