英文:
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的值时,它不可能指向基类中的不同值。
此外,如注释中所指出的,B和A的__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__x,B 具有 _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("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)
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:
>>> obj = C()
>>> 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:
>>> 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论