[英]Changing type of self after call to super()
I have a little trouble with Python's inheritance model.我对 Python 的 inheritance model 有点麻烦。 In particular, when calling a method using super(), the method of the super class is invoked, but the self reference type does not change.
特别是使用super()调用方法时,调用了super class的方法,但是自引用类型没有改变。 Hence, calling methods using self will point to the derived class.
因此,使用 self 调用方法将指向派生的 class。
I guess it's easier to understand in code:我想在代码中更容易理解:
class A:
def fun1(self, p1, p2):
print('A:fun1')
return f'a: {p1} {p2}'
def fun2(self, p1):
print('A:fun2')
return self.fun1(p1, p1)
class B(A):
def fun1(self, p1, p2):
print('B:fun1')
return super(B, self).fun1(f'b{p1}', f'b{p2}')
def fun2(self, p1):
print('B:fun2')
return super(B, self).fun2(f'b{p1}')
b = B()
print(b.fun1('1', '2'))
print(b.fun2('3'))
In the above code we have to functions fun1
and fun2
, where one is an 'optimized' version of the other, calling it via self
.在上面的代码中,我们必须使用函数
fun1
和fun2
,其中一个是另一个的“优化”版本,通过self
调用它。 The derived class changes the functionality of both functions but is still based on their super versions.派生的 class 改变了这两个函数的功能,但仍然基于它们的超级版本。
When executing this, we'll have this output:执行此操作时,我们将拥有此 output:
B:fun1
A:fun1
a: b1 b2
B:fun2
A:fun2
B:fun1
A:fun1
a: bb3 bb3
When invoking B.fun2
using super()
correctly forwards the call to A.fun2
.使用
super()
正确调用B.fun2
时,会将调用转发到A.fun2
。 But: the type of self
does not change and A.fun2
is now not based on A.fun1
anymore, but on B.fun1
, because self
has type B
.但是:
self
的类型没有改变, A.fun2
现在不再基于A.fun1
,而是基于B.fun1
,因为self
具有B
类型。
I understand why, but is there a way to change this behaviour?我明白为什么,但有没有办法改变这种行为? I'd really like
self
to always call functions of the 'self' class.我真的很希望
self
总是调用“self”class 的函数。
Short answer: use __private
names or store the “base” object in a field instead of subclassing.简短的回答:使用
__private
名称或将“基础” object 存储在字段中而不是子类化。
Inheritance in python allows classes to override methods of the same name in their base classes. python 中的 Inheritance 允许类覆盖其基类中的同名方法。 The lookup is done in the method resolution order .
查找是按方法解析顺序完成的。
The only names that do not follow this shadowing are names beginning with two underscores .唯一不遵循此阴影的名称是以 两个下划线开头的名称。 Python internally rewwrites every attribute lookup on
self
from __private
to _ClassName__private
, so that they do not collide with each other. Python 在内部将
self
上的每个属性查找从__private
重写为_ClassName__private
,这样它们就不会相互冲突。
The other way is to just store your base object in a field — it will then make it impossible to overwrite anything on it.另一种方法是将你的基础 object 存储在一个字段中——这样就不可能覆盖上面的任何内容。 But I think the double underscore way is superior, since it also exposes all the unaltered access to the base object (you can get around it by defining
__getattr__(self, x)
resorting to getattr(super(), x)
if hiding the base object is desired).但我认为双下划线方式更好,因为它还公开了对基础 object 的所有未更改访问(如果隐藏基础,您可以通过定义
__getattr__(self, x)
诉诸getattr(super(), x)
来绕过它需要 object)。
By the way, here you can use super()
without arguments.顺便说一句,这里你可以使用
super()
而不使用 arguments。 This is the simple case described in the docs .这是文档中描述的简单案例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.