[Tutor] Strange namespace issue
Alexandre Ratti
alex@gabuzomeu.net
Wed, 03 Apr 2002 20:39:36 +0200
Hello,
I ran into this strange issue a couple of days ago. I'd be grateful if
someone could explain it. Sorry for this long, rambling account; I tried to
make it as clear as possible.
I wanted to parse a string into a tree for later processing. I created this
class (based on the Trees chapter of "How to think like a computer
scientist"). It defines a "multiple" tree, eg. a tree whose nodes can have
several subnodes.
Here is the 1st version:
class TreeNode:
"Node to build multiple trees."
def __init__(self, cargo = None, nodeList = []):
self.cargo = cargo
self.nodeList = nodeList
def addNode(self, node):
"Add a TreeNode instance to the child node list."
if node:
self.nodeList.append(node)
def __getitem__(self, index):
"Return a child node."
return self.nodeList[index]
...
I used another class to recursively cut a text snippet into pieces and
store them in tree nodes, thus building a tree. Here is a short except of
the main parsing method. The point I want to make is that I invoked the
class using "node = TreeNode(someCargoObject)"; eg. I did not pass a list
argument when creating a node instance. Then I appended the new node to the
current tree node.
def doParse(self, patternList, tree, workText):
"Recursively parse wiki formatting into a tree."
...
pattern = NullPattern(textBefore)
node = TreeNode(pattern)
tree.addNode(node)
self.doParse(patternList[:-1], node, textBefore)
When trying to print out the tree content, I ran into an endless loop. Here
is the printing code (I eventually added a test to break out of the loop
before I had to forcefully close PythonWin :-).
testDict = {}
def printTree(tree, level = 0):
if not tree:
return
print " " * level + "|_", [str(tree.cargo)]
for node in tree:
if testDict.has_key(id(node)):
print id(node), str(node)
raise "Duplicated Node Error"
else:
testDict[id(node)] = None
printTree(node, level + 1)
The tree looked OK (eg. I printed out the id for every node and it looked
sane). After a long fight, I realised that all nodes used a common nodeList
instance (with the same id)...
When I rewrote the __init__ method, the problem went away:
def __init__(self, cargo = None, nodeList = None):
"Initialise the node instance."
self.cargo = cargo
if nodeList:
self.nodeList = nodeList
else:
self.nodeList = []
And now I get to my query: when I wrote...
def __init__(self, cargo = None, nodeList = []):
self.cargo = cargo
self.nodeList = nodeList
... I expected self.nodeList to be initialised to a new, empty list if the
constructor was called without a nodeList argument. Somehow it failed. I
had to use "nodeList = None" in the argument list and then to specify
"self.nodeList = []" to initialise the list properly.
What did I miss? Is this the normal behaviour?
This happened on WinNT 4 with Python 2.1.2. I can upload the complete code
somewhere if needed.
Many thanks.
Alexandre