Search code examples
pythonparameter-passingtypeerrorkeyword-argument

Why does passing keyword/named arguments produce error when name has double underscores prior to the name?


While running a trading algorithm, I ran into the following issue that I tried to reproduce in the following way:

Suppose I have one algorithm named algo1.py and another named algo2.py.

Here's algo2.py...

class mathOperations():

    def __init__(self):
        self.value = 0

    def sum(self, __a = 0, __b = 0):
        return (__a + __b)

Here's algo1.py...

from algo2 import mathOperations


math = mathOperations()
print(math.sum(__a = 56, __b = 44))

When I run algo1.py, I get the following message:

Traceback (most recent call last):
  File "algo1.py", line 5, in <module>
    print(math.sum(__a = 56, __b = 67))
TypeError: sum() got an unexpected keyword argument '__a'

However, when I remove the '__' or two underscores from the front of the named arguments in both algorithms, this error goes away. Could someone please explain to me why?


Solution

  • See the documentation about name mangling:

    Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.

    That explains the why. The reason for this weird feature existing in the first place is described in the tutorial here (TL;DR: it's a hack to avoid name clashes with names defined by subclasses).

    The solution is easy: don't use names with two leading underscores when defining the arguments for methods.