【问题标题】:Variables accessed by a function within a class [duplicate]类中的函数访问的变量[重复]
【发布时间】:2019-12-05 15:58:36
【问题描述】:

为什么 val_n 函数返回 self.__n 的旧值?在我看来,如果 obj.__n 已更新为 3,调用 self.val__n 应该返回 3 而不是 2。

class myClass:
    def __init__(self,n=1):
        self.__n=n
    def val_n(self):
        return self.__n

#create an instance, __n is 2
obj=myClass(2)

#update __n to 3
obj.__n=3

#verify obj.__n has changed from 2 to 3
print(obj.__n)

#why does this still return 2?
print(obj.val_n())

【问题讨论】:

  • 副本没有说明为什么obj.__n = 3 似乎改变了值。答案是这个赋值,因为它不会出现在方法定义中,所以创建了一个 new 属性,其名称实际上是__n,而不是_myClass__n。使用dir(obj) 表明两个名称的属性在赋值之后都存在。
  • @chepner 是的,同意。这个问题并不是真正的重复。这个问题要简单得多,不需要说明公共方法和私有方法之间的区别。

标签: python


【解决方案1】:

这是基于 Python 的名称修饰功能。对类属性使用前导双下划线意味着 Python 将使用名称修饰。

class X:
    __attr = None

x = X()
x.__attr
# raises AttributeError
x._X__attr
# None

Python 将类 X 中的名称 __attr 转换为 _X__attr 以便在子类化时,如果子类也定义了 __attr 但需要父类的属性,则该属性不太可能被覆盖。

当您执行x.__n = 3 时,您不会覆盖类中定义的属性,因为它已成为任何外部访问器的x._myClass__n。相反,您正在创建一个新属性(并且 Python 在分配 x.__n 之前并没有真正检查它是否已经是对象的属性 - 这就是为什么没有引发 AttributeError 的原因)。

【讨论】:

  • 谢谢 - 这是一个非常清晰的解释,正是我想要的。
猜你喜欢
  • 1970-01-01
  • 2020-06-16
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 2018-06-16
  • 2013-09-17
相关资源
最近更新 更多