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

Issue with Python single and double underscore variables

提问人:p0lAris 提问时间:4/1/2013 更新时间:11/13/2021 访问量:3769

问:

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

我有以下代码:

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()

对于一个数字对象,比如说,对于下面的语句,我总是返回 None——n = Number(KST.Constant(..))

 n.expressionType()

现在,如果我将双下划线更改为单下划线,则一切都有效。我理解私有变量和半私有变量之间的区别,但为什么会发生这种情况——我不知道。此外,我在许多其他地方都使用了“__”,一切似乎都很好。

Python 继承

评论

0赞 Lennart Regebro 4/1/2013
Python 中对象名称前单下划线和双下划线的含义的可能重复
0赞 dnozay 4/1/2013
如果您也定义了 on,这将起作用。但从代码重复的角度来看,您可能希望使用单个下划线。expressionTypeNumber

答:

7赞 Lennart Regebro 4/1/2013 #1

带有双下划线的属性名称被“篡改”,使得在子类中更难有冲突的名称。

因此,请使用单下划线。

评论

0赞 p0lAris 4/1/2013
知道了。我明白这个问题。我现在做的是——。你认为这是一种更好的方法吗?显然,我已将 添加到 的构造函数中。Expression.__init__(self, value.elementType())expressionTypeExpression
0赞 Lennart Regebro 4/1/2013
@flippex17_ 是的,叫它.python.org/dev/peps/pep-0008element_type() ;-)
0赞 p0lAris 4/1/2013
对不起,我没有得到那个。我的问题是——“我应该使用单个下划线还是最终改变我调用超类构造函数的方式”?我不关心变量命名,因为我使用 Camel 命名约定。
0赞 Lennart Regebro 4/1/2013
是的,使用单下划线。我认为我的答案非常清楚,很难被误解。
0赞 dnozay 4/1/2013 #2

这是因为名称篡改正在发生。

  • expressionType在 中定义。Expression
  • n.__expressionType将转换为 .n._Expression__expressionType
  • 如果将相同的方法复制粘贴到类中,则由于方法解析顺序,它将转到 where will mean 中出现的定义。expressionTypeNumberNumberself.__expressionTypeself._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

但是,存在代码重复,因此使用单个下划线更好,因为它不会破坏属性的名称。

1赞 Pithikos 10/1/2014 #3

正如其他人所指出的,“诽谤”发生了。简单来说,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