Your example would work in some programming languages. (For example
C
allows this, via pointer references.) The reason it doesn't work here is because of how the semantics of method-calling is defined in Python.
Name binding in Python
When you write
self.data = None
this assigns a new name (self.data
) to the object None
.
With self.Recur
defined as
def Recur(self, node, data):
if node is None:
node = data
the following gives a new name to None
in the context of the Recur
method:
node
.
self.Recur(self.data, data)
However, this new name (node
) in the inner scope for the same object has no co-relation to the other name (self.data
) in the outer scope.
When you write
node = data
this assigns the name node
to a new value, namely the value to which
the name data
refers. Again, this does not affect the name
self.data
. For more information, check out this blog post.
How to do what you want
On the other hand, if you want Recur
to be able to assign a value to any attribute of the test
object, it can be done. Here
is one way to achieve it:
class test:
def __init__(self):
self.data = None
def Recur(self, nodeName, data):
if self[nodeName] is None:
self[nodeName] = data;
def Insert(self, data):
self.Recur("data", data)
__getitem__ = self.__getattr__
__setitem__ = self.__setattr__
NB: This code is untested
This allows Insert
to choose the name ("data"
) to which Recur
assigns a value. Recur
, for its part, uses the dict-key get-item syntax of Python to assign a value to the key data
in our quasi-dict object; however, we set the get-item and set-item semantics to be the same as the get-attribute and set-attribute semantics with the last two lines — this ensures that self["name"]
means the same thing as self.name
. A less mysterious implementation would be:
def __getitem__(self, key):
return self.__getattr__(key)