【问题标题】:Trouble accessing python superclass attributes [duplicate]访问python超类属性时遇到问题[重复]
【发布时间】:2014-05-07 15:10:46
【问题描述】:

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

class Foo:

    def __init__(self, foo):
        self.__foo = foo


class Bar(Foo):

    def bar(self):
        print self.__foo

当我尝试在 Bar 的实例上调用 bar 方法时,它失败了。

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'

我的理解是这段代码应该基于twoother问题工作,为什么不呢?

【问题讨论】:

  • @MartijnPieters 链接到的问题肯定提供了一个兼容的答案,但我认为如果不先知道答案,我不会知道去哪里看!
  • 别担心,我没想到你会这样。如果作为副本关闭,您的帖子将作为另一个问题的路标,以便将来搜索相同问题的任何人都可以更轻松地找到它。
  • @MartijnPieters 同意。这就是为什么它也得到了我的近距离投票。

标签: python inheritance


【解决方案1】:

简单。 __foo开头有2个下划线,所以假设是类私有方法,转化为_Classname__method

当您请求访问Bar 对象上的属性时,它会询问Bar 类是否具有此方法(不是Foo 类),因此self.__foo 始终与self._Bar__foo 相同。

来自documentation

当一个以文本形式出现在类定义中的标识符开始时 有两个或更多下划线字符且不以两个或更多结尾 下划线,它被认为是该类的私有名称。私人的 在生成代码之前,名称被转换为更长的形式 他们。转换插入类名,前导 删除下划线并在前面插入一个下划线 姓名。例如,标识符 __spam 出现在名为 Ham 将被转换为 _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 语句不会导致任何AssertionErrors。

__getattribute__ 方法添加到Bar 类以捕获对Bar 对象的所有请求:

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 除外):

Requested bar
Accessing __foo from bar
Requested _Bar__foo # AttributeError follows

如您所见,如果您请求的属性有 2 个前导下划线,Python 会即时重命名它。

【讨论】:

  • 我没有意识到发生了任何名称错误,感谢您的解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多