Output of below program show A=30, B-30 and C=30 any on can explain why not A=10, B=20 and C=30?

huangapple go评论70阅读模式
英文:

Output of below program show A=30, B-30 and C=30 any on can explain why not A=10, B=20 and C=30?

问题

class A:
    def __init__(self, x):
        self.x = x  # 将 self.x 的赋值修正为 self.x = x
    def show(self):
        print("A:", self.x)


class B(A):
    def __init__(self):
        super().__init__(10)  # 将 self.x 的赋值修正为 super().__init__(10)

    def show(self):
        super().show()
        print("B:", self.x)


class C(B):
    def __init__(self):
        self.x = 30

    def show(self):
        super().show()
        print("C:", self.x)


obj = C()
obj.show()
英文:
class A:
    def __init__(self, x):
        self.x
    def show(self):
        print("A:", self.x)


class B(A):
    def __init__(self):
        self.x = 20

    def show(self):
        super().show()
        print("B:", self.x)


class C(B):
    def __init__(self):
        self.x = 30

    def show(self):
        super().show()
        print("C:", self.x)


obj = C()
obj.show()

Tried the code and different cobbination but got answer A=30, B-30 and C=30 Need A=10, B=20 and C=30 in mentioned.

答案1

得分: 2

只有一个对象(它是C的一个实例),所以在每种情况下,x都指向相同的变量。因此,当你打印x的值时,它不可能指向基类中的不同值。

此外,如注释中所指出的,BA__init__方法实际上从未被调用(即使被调用,也只会每次覆盖x的当前值,因此它总是显示相同的值)。

英文:

There's only one object (which is an instance of C), so x refers to the same variable in each case. Thus, when you print the value of x, it couldn't possibly refer to separate values in the base classes.

Also, as indicated in the comments, the __init__s for B and A are never actually called (and even if they were, you'd just be overwriting the current value of x every time, so it would always show the same value).

答案2

得分: 1

只有 C__init__ 方法被调用,self.x 只被设置为 30。即使你使用了 super().__init__(),对 x 的每次赋值都会覆盖任何先前的赋值 - 你仍然会得到一个值,具体取决于 super 调用和赋值的顺序。一个实例只能有一个给定属性名称的值。

如果你真的想要不同的类具有不同的值,并且假设公共接口的其余部分是正确的,一个工作的实现看起来会像这样:

class A:

    def __init__(self, x):
        self.__x = x

    def show(self):
        print("A:", self.__x)


class B(A):

    def __init__(self):
        super().__init__(10)
        self.__x = 20

    def show(self):
        super().show()
        print("B:", self.__x)


class C(B):

    def __init__(self):
        super().__init__()
        self.__x = 30

    def show(self):
        super().show()
        print("C:", self.__x)

__x 用作属性名称会触发名称修饰(请参阅Designing for Inheritance),这意味着 A 实际上具有 _A__xB 具有 _B__x 等等。这是故意的,旨在防止子类覆盖其超类的属性 - 这通常不是一个好主意(这不是制作“私有”属性的惯用方式,例如),但如果你希望每个子类都有一个单独的值,这就是你应该这样做的方式。在使用时:

>>> obj = C()
>>> obj.show()
A: 10
B: 20
C: 30

但是,请注意,外部访问 __x 也是被阻止的,你必须明确指定要访问哪个 __x

>>> obj.__x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__x'
>>> obj._A__x
10
>>> obj._B__x
20
>>> obj._C__x
30
英文:

Only C's __init__ method gets invoked, self.x is only ever set to 30. Even if you did use super().__init__(), each assignment to x would overwrite any previous assignment - you'd still end up with one value, which one would depend on the order of the super calls vs. assignments. An instance can only have one value for a given attribute name.

If you really do want the different classes to have different values, and assuming that the rest of the public interface is correct, a working implementation would look something like:

class A:

    def __init__(self, x):
        self.__x = x

    def show(self):
        print(&quot;A:&quot;, self.__x)


class B(A):

    def __init__(self):
        super().__init__(10)
        self.__x = 20

    def show(self):
        super().show()
        print(&quot;B:&quot;, self.__x)


class C(B):

    def __init__(self):
        super().__init__()
        self.__x = 30

    def show(self):
        super().show()
        print(&quot;C:&quot;, self.__x)

Using __x as the attribute name invokes name mangling (see Designing for Inheritance), which means A actually has _A__x, B has _B__x, and so on. This is deliberately intended to prevent subclasses overriding the attributes of their superclasses - it's not a good idea generally (it's not the idiomatic way to make "private" attributes, for example), but if you want each one to have a separate value this is how you do it. In use:

&gt;&gt;&gt; obj = C()
&gt;&gt;&gt; obj.show()
A: 10
B: 20
C: 30

However, note that external access to __x is also prevented, you have to be specific about which __x:

&gt;&gt;&gt; obj.__x
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
AttributeError: &#39;C&#39; object has no attribute &#39;__x&#39;
&gt;&gt;&gt; obj._A__x
10
&gt;&gt;&gt; obj._B__x
20
&gt;&gt;&gt; obj._C__x
30

huangapple
  • 本文由 发表于 2023年7月31日 21:30:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76804136.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定