Trouple访问python超类属性 [英] Trouple accessing python superclass attributes

查看:495
本文介绍了Trouple访问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 的实例上的code>方法,它失败。

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个下划线,因此它被假定为class-private方法,并且它被转换为 _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.

来自文档


在类定义中以文本方式出现的标识符以两个或多个下划线字符开头
,并且不以两个或更多
下划线结尾,它被视为该类的私有名称。在为
生成代码之前,将私有
名称转换为更长的形式。转换插入类名,在
名称前面删除了前导
下划线并插入了一个下划线。例如,名为
Ham的类中出现的标识符__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.

添加 __ getattribute __ 方法到 Bar 类来捕获对 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.

这篇关于Trouple访问python超类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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