Python单下划线和双下划线变量的问题

5

我不确定我做错了什么,或者为什么会这样。

以下是我的代码:

class Expression (Node):
  """
  ...
  """

  def __init__ (self):
    self.__expressionType = None


  def expressionType (self):
    return self.__expressionType


class Number (Expression):
  """
  Number .
  """

  def __init__ (self, value):
    """
    Value is an entry of type Constant.
    """
    Expression.__init__(self)
    assert isinstance (value, KST.Constant)
    self.__constant = value
    self.__expressionType = value.elementType()

对于一个数字对象,例如 n = Number(KST.Constant(..)),对于以下语句,我总是会得到 None:
 n.expressionType()

现在,如果我将双下划线改为单下划线,一切都能正常运行。我理解私有和半私有变量之间的区别,但为什么会出现这种情况——我不知道。此外,我在许多其他地方使用“__”,似乎也都能正常工作。

可能是重复的问题:Python中对象名称前单下划线和双下划线的含义 - Lennart Regebro
如果你在Number上也定义了expressionType,那么这将起作用。但从代码复制的角度来看,您会想要使用一个下划线。 - dnozay
3个回答

7

双下划线开头的属性名被称为“私有变量”,以使其在子类中更难产生命名冲突。

因此,请使用单个下划线。


我明白了。我理解了这个问题。现在我要做的是——Expression.__init__(self, value.elementType())。你认为这样做更好吗?显然,我已经将expressionType添加到了Expression的构造函数中。 - p0lAris
@flippex17_ 是的,称其为 element_type()。 http://www.python.org/dev/peps/pep-0008/ ;-) - Lennart Regebro
很抱歉,我没有理解你的意思。我的问题是:“我应该使用单个下划线还是改变调用超类构造函数的方式?” 我不关心变量命名,因为我使用驼峰命名约定。 - p0lAris
是的,请使用单个下划线。我认为我的回答已经非常清楚,很难误解。 - Lennart Regebro

1
正如其他人指出的那样,“名称重整”会发生。简单来说,Python会更改变量名,以便程序员无法通过纯内存访问它们。
示例:
class A():
  var1 = 10    # typical variable
  __var2 = 20  # double-underscored variable

现在你会注意到无法访问双下划线变量。
>>> A.var1
10
>>> A.__var2
  AttributeError: type object 'A' has no attribute '__var2'

除非您知道Python如何更改变量名称

>>> a._A__var2
20

这基本上是获得与Java和其他编程语言中private相同的行为,其中您不希望程序员意外更改值。

0

这是因为 名称重整 正在发生。

  • expressionTypeExpression 中被定义。
  • n.__expressionType 将转换为 n._Expression__expressionType
  • 如果你将相同的 expressionType 方法复制粘贴到类 Number 中,那么由于方法解析顺序,它会去到出现在 Number 中的定义,其中 self.__expressionType 将意味着 self._Number__expressionType

n._Expression__expressionType != n._Number__expressionType

这实际上是可行的:

class Expression(Node):
  def __init__(self):
    self.__expressionType = None
  def expressionType(self):
    return self.__expressionType

class Number(Expression):
  def __init__ (self, value):
    Expression.__init__(self)
    assert isinstance (value, KST.Constant)
    self.__constant = value
    self.__expressionType = value.elementType()
  def expressionType (self):
    return self.__expressionType

然而,存在着代码重复的情况,因此使用单个下划线更好,因为它不会弄乱属性的名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接