11

我有以下代码。

class Foo(object):
     def __init__(self):
         self.__baz = 40
     def foo(self):
         print self.__baz

class Bar(Foo):
     def __init__(self):
         #super(Bar, self).__init__()
         self.__baz = 21
     def bar(self):
         print self.__baz

x = Bar()
x.foo()
x.bar()

我收到此错误:

Traceback (most recent call last):
  File "classes.py", line 15, in <module>
    x.foo()
  File "classes.py", line 5, in foo
    print self.__baz
AttributeError: 'Bar' object has no attribute '_Foo__baz'

为什么foo方法没有继承在Bar.

编辑:它工作正常,如果你调用 super 被注释掉。

4

4 回答 4

9

双下划线属性的名称根据当前/包含的命名空间进行了修改。在函数foo中,当前命名空间是Foo这样的,当 python 查找时,由于名称修改方案self.__baz,它实际上会查找。self._Foo__baz由于Foo您实际上没有设置__baz属性,因此该类没有_Foo__baz属性(它具有_Bar__baz属性,因为您self.__baz在 中的方法中设置Bar)。

当然,您可能已经注意到,如果您调用Foo.__init__(self)Baz.__init__直接或通过super),您会看到问题消失了,因为Foo.__init__集合__baz(即_Foo__baz)。

于 2013-09-27T04:11:50.807 回答
3

当您像在 python 中那样使用双下划线命名变量时,成员名称将被混淆。声明__baz给你一个成员_Bar__baz

class Bar(Foo):
 def __init__(self):
     #super(Bar, self).__init__()
     self.__baz = 21
 def bar(self):
     print self._Bar__baz

x = Bar()
x.bar()
>>> 21
于 2013-09-27T04:10:54.770 回答
2

通过在__baz您请求的“名称修改”上使用最初的双下划线来创建“私有”变量。它记录在这里:

http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

如果您将名称从更改__baz为 justbaz您的代码将如图所示工作。

于 2013-09-27T04:11:48.193 回答
1

从 python 3.6 开始,我们现在可以使用该__init_subclass__函数,该函数__init__在 Child 之前被自动调用。

class Foo(object):
     def __init_subclass__(self):
         self.__baz = 40
     def foo(self):
         print(self.__baz)

class Bar(Foo):
     def __init__(self):
         self.__baz = 21
     def bar(self):
         print(self.__baz)

x = Bar()
x.foo()
x.bar()

输出

40
21
于 2020-07-09T18:30:24.420 回答