无法访问python超类属性 [英] Trouble accessing python superclass attributes

查看:75
本文介绍了无法访问python超类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个课,大致采用以下形式:

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 AssertionErrors.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆