Trouple accessing python superclass attributes [duplicate]

孤人 提交于 2019-12-31 04:02:09

问题


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

When I try to invoke the bar method on an instance of Bar, it fails.

b = Bar('foobar')    
b.bar()

Result:

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?


回答1:


Simple. __foo contains 2 underscores in the beginning, so it's assumed to be class-private method and it's transformed into _Classname__method.

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.

From the documentation:

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.

If you modify your code slightly

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 statements will not cause any AssertionErrors.

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()

There will be 3 lines (apart from AttributeError) in the output:

Requested bar
Accessing __foo from bar
Requested _Bar__foo # AttributeError follows

As you can see, if attribute you are requesting has 2 leading underscores, Python is renaming it on the fly.



来源:https://stackoverflow.com/questions/23521600/trouple-accessing-python-superclass-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!