【发布时间】:2017-08-13 23:22:33
【问题描述】:
这是来自Effective Pʏᴛʜᴏɴ 的示例,我显然遗漏了一些内容。我添加了一些印刷品来帮助说服自己,但我还是有点不清楚。
我知道当您尝试访问继承的私有变量时,它会失败,因为在子实例字典中,名称已被破坏(下面的最后一行,尝试访问 a.__value 正确失败,因为实例字典包含修改后的版本_ApiClass__value)。
我被绊倒的地方是为什么继承的方法get 没有这个问题。如果您在对get 的调用中打印self.__dict__,您可以看到我们仍在使用相同的Child 实例字典,就像我们尝试直接从子代(其中包含损坏的名称)使用虚线访问一样只要)。此方法中的点属性访问以某种方式正确地转换为损坏的名称并检索私有变量。
我对属性访问的理解是,在幕后,本质上发生的事情(尽管简化了)是a.__value 基本上是a.__dict__['__value']。这是有道理的,当您尝试直接访问继承的私有变量时证明了这一点,因为它失败了,因为只有损坏的名称在 Child 字典中。然而,继承的方法get,它在来自 Child 的同一个实例 dict 上运行,与点访问一起工作,所以它显然不是在做 a.__dict__['__value'],而是在做 a.__dict__['_ApiClass__value']。
这里有什么区别导致来自get 方法内的私有属性访问意识到损坏的名称而不是来自子级的类似属性访问?
class ApiClass():
def __init__(self):
self.__value = 5
def get(self):
print(self.__dict__['_ApiClass__value']) #succeeds
print(self.__dict['__value']) #fails bc name mangle
return self.__value # How is this translated to '_ApiClass_value'
# but a similar instance lookup fails?
class Child(ApiClass):
def __init__(self):
super().__init__()
self._value = 'hello'
a = Child()
print(a.__dict__)
print(a.get()) # Works, but instance dict has no '__value' key?
print(a.__value) # Fails because name mangled to '_ApiClass_value'.
【问题讨论】:
-
你
ApiClass.get()第二行的评论表明该行不起作用,但没关系。除了在您尝试访问a.__value的最后一行之外,我可以毫无错误地运行此代码。 -
mangling 规则在文档中解释得很清楚:docs.python.org/2/tutorial/…
-
@Craig - 修正了第二行的错字,对此感到抱歉。也就是说,将我推荐给文档并不是特别有用。
标签: python inheritance private