无法访问python超类属性 [英] Trouble accessing python superclass attributes
问题描述
我有两个课,大致采用以下形式:
I have two classes that loosely take the form below:
class Foo:
def __init__(self, foo):
self.__foo = foo
class Bar(Foo):
def bar(self):
print self.__foo
当我尝试在Bar
的实例上调用bar
方法时,它将失败.
When I try to invoke the bar
method on an instance of Bar
, it fails.
b = Bar('foobar')
b.bar()
结果:
Traceback (most recent call last):
File "foobar.py", line 14, in <module>
b.bar()
File "foobar.py", line 10, in bar
print self.__foo
AttributeError: Bar instance has no attribute '_Bar__foo'
我的理解是,此代码应基于两个
My understanding is that this code should work based on two other questions, why doesn't it?
推荐答案
简单. __foo
开头包含2个下划线,因此假定它是类专用方法,并且已转换为_Classname__method
.
Simple. __foo
contains 2 underscores in the beginning, so it's assumed to be class-private method and it's transformed into _Classname__method
.
当您请求访问在Bar
对象上这样命名的属性时,它会询问Bar
类是否具有此方法(不是Foo
类),因此self.__foo
始终与self._Bar__foo
相同.
When you request access to the attribute named as such on Bar
object it asks Bar
class if it has this method (not Foo
class), so self.__foo
is always the same as self._Bar__foo
.
从文档:
当在类定义中以文本形式出现的标识符开始时 有两个或多个下划线字符,且不以两个或多个结尾 强调,它被认为是该类的专用名称.私人的 在为以下代码生成代码之前,将名称转换为更长的形式 他们.转换将插入类名,并以前导 删除下划线并在其前面插入一个下划线 姓名.例如,标识符__spam出现在名为的类中 火腿将被转换为_Ham__spam.
When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam.
如果您稍微修改代码
class Foo:
def __init__(self, foo):
self.__foo = foo
assert hasattr(self, '_Foo__foo'), 'Attribute has been just created'
class Bar(Foo):
def bar(self):
assert hasattr(self, '_Foo__foo'), 'No errors, thanks to inheritance'
assert
语句不会引起任何AssertionError
s.
assert
statements will not cause any AssertionError
s.
在Bar
类中添加__getattribute__
方法以捕获对Bar
对象的所有请求:
Add __getattribute__
method to Bar
class to capture all requests to Bar
objects:
class Bar(Foo):
def bar(self):
print('Accessing __foo from bar')
print(self.__foo)
def __getattribute__(self, name):
print('Requested', name)
return super().__getattribute__(name)
b = Bar('foobar')
b.bar()
输出中将有3行(除了AttributeError
之外):
There will be 3 lines (apart from AttributeError
) in the output:
Requested bar
Accessing __foo from bar
Requested _Bar__foo # AttributeError follows
如您所见,如果您要请求的属性有2个下划线,则Python会即时对其进行重命名.
As you can see, if attribute you are requesting has 2 leading underscores, Python is renaming it on the fly.
这篇关于无法访问python超类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!