我有以下代码。
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
中继承。
编辑:如果你打电话给被评论出来的超级网站,它可以正常工作。
答案 0 :(得分:7)
双下划线属性基于当前/包含命名空间使其名称损坏。在函数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__
,您会看到问题消失,因为{{1设置__baz
(即_Foo__baz
)。
答案 1 :(得分: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
答案 2 :(得分:2)
通过在__baz
上使用初始双下划线,您请求“名称修改”以创建“私有”变量。它记录在这里:
http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
如果您将名称从__baz
更改为baz
,则您的代码将如图所示。
答案 3 :(得分:0)
从python 3.6开始,我们现在可以使用__init_subclass__
函数,该函数在Child的__init__
之前自动调用。
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