5

I am unsure what I am doing wrong; or why this is the case.

I've the following code:

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

For a number object say n = Number(KST.Constant(..)), I am always returned None for the following statement—

 n.expressionType()

Now if I change the double underscores to single ones, it all works. I understand the difference between private and semi-private variables but why this is happening — I've no idea. Also, I've used "__" in a number of other places and it all seems to work fine.

p0lAris
  • 4,750
  • 8
  • 45
  • 80
  • possible duplicate of [The meaning of a single- and a double-underscore before an object name in Python](http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python) – Lennart Regebro Apr 01 '13 at 05:34
  • this would work if you defined `expressionType` on `Number` as well. but from code-duplication perspective, you would want to use a single underscore. – dnozay Apr 01 '13 at 05:45

3 Answers3

7

Attribute names with double underscores are "mangled" to make it harder to have conflicting name in subclasses.

So use single underscores.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • I got it. I understood the issue. What I now do is — `Expression.__init__(self, value.elementType())`. Do you think this is a better way of doing it? Obviously, I've added the `expressionType` to the constructor of `Expression`. – p0lAris Apr 01 '13 at 05:33
  • @flippex17_ Yes, call it `element_type()`. http://www.python.org/dev/peps/pep-0008/ ;-) – Lennart Regebro Apr 01 '13 at 05:35
  • I am sorry I didn't get that. My question was— 'should I use a single underscore or end up changing the way I call the constructor for the super class'? I am not concerned with variable naming as I use the Camel naming convention. – p0lAris Apr 01 '13 at 05:38
  • Yes, use single underscores. I think my answer was perfectly clear in that and very hard to misunderstand. – Lennart Regebro Apr 01 '13 at 05:42
1

As others pointed out, "namemangling" occurs. In simple terms, Python will change the variable names so that the programmer can't access them by pure memory.

Example:

class A():
  var1 = 10    # typical variable
  __var2 = 20  # double-underscored variable

Now you'll notice that you can't access the double-underscored variable..

>>> A.var1
10
>>> A.__var2
  AttributeError: type object 'A' has no attribute '__var2'

..unless you know how Python changes your variable names

>>> a._A__var2
20

This is essentially getting the same behaviour as private in Java and other programming languages where you don't want programmers accidentally changing values.

Pithikos
  • 18,827
  • 15
  • 113
  • 136
0

This is because name mangling is happening.

  • expressionType is defined in Expression.
  • n.__expressionType will translate to n._Expression__expressionType.
  • if you copy-paste the same expressionType method to the class Number, then because of method resolution order, it would go the the definition that appears in Number where self.__expressionType would mean self._Number__expressionType.

n._Expression__expressionType != n._Number__expressionType.

This would actually work:

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

However, there is code duplication, so using a single underscore is better because it won't mangle the name of the attribute.

dnozay
  • 23,846
  • 6
  • 82
  • 104