简体   繁体   English

调用 super() 后更改 self 的类型

[英]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 .在上面的代码中,我们必须使用函数fun1fun2 ,其中一个是另一个的“优化”版本,通过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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM