Not Incrementing

Dave Angel davea at ieee.org
Thu Dec 31 13:01:49 EST 2009


Victor Subervi wrote:
> Hi;
> This "pseudo-code" snippet was given to me by Dennis on this list (whose
> last name escapes me):
>
> def printTree(allTrees, level=0):
>   tree = []
>   for aTree in allTrees:
>     for name in sorted(aTree.keys()):
>       tree.append("%s%s" % ("\t" * level, name))
>       printTree(aTree[name], level + 1)
>   return tree
>
> The code returns all the categories ("name") just fine. It doesn't, however,
> increment level. I know from my tests that printTree is only called twice
> (once for each store) and about half a dozen times recursively within one of
>   

It increments just fine, but you don't use the values it then 
generates.  See below.
> those stores. Why doesn't this increment? Full code follows.
> TIA,
> beno
>
> #!/usr/bin/python
>
> import sys,os
> sys.path.append(os.getcwd())
> import MySQLdb
> from login import login
> import re, string
>
> def printTree(allTrees, level=0):
>   tree = []
>   for aTree in allTrees:
>     for name in sorted(aTree.keys()):
>       tree.append("%s%s" % ("\t" * level, name))
>       printTree(aTree[name], level + 1)
>       print '1'
>   return tree
>
>   
You have to decide what printTree is intended to do.   Is it printing 
stuff (which the name implies), or is it building a result list (which 
the return statement implies) ?  From the rest of the code, I assume the 
latter.  So give it a different name, and fix the recursion.

When it recurses, it doesn't use the return value from the inner call.  
Presumably you want to "extend" the list called "tree" each time you 
recurse.  At this point, you also have to decide what order the combined 
list needs to be in, but maybe you've already done that.
> def expand(fetched):
>   aDict = {}
>   for (name, ) in fetched:
>     aDict[name] = {}
>   return aDict
>
> def getChildren(levelDict, store, level = 0):
>   user, passwd, db, host = login()
>   db = MySQLdb.connect(host, user, passwd, db)
>   cursor = db.cursor()
>   MAXLEVEL = 7
>   if level > MAXLEVEL:
>     return  #possibly the data has a cycle/loop
>   for name, data in levelDict.iteritems():
>     sql = '''select * from categories%s as c
>       inner join categoriesRelationships%s as r
>       on c.ID = r.Child
>       inner join categories%s as p
>       on r.Parent = p.ID
>       where p.Category = "%s"''' % (store[0].upper() + store[1:],
> store[0].upper() + store[1:], store[0].upper() + store[1:], name)
>     cursor.execute(sql)
>     levelDict[name] = expand(cursor.fetchall())
>     # recursive call to do next level
>     getChildren(levelDict[name], level + 1)
>   # no data return as we are mutating dictionaries in place
>
> def catTree(allStores):
>   user, passwd, db, host = login()
>   db = MySQLdb.connect(host, user, passwd, db)
>   cursor = db.cursor()
>   finalTrees = []
>   returnFlag = ''
>   for store in allStores:
>     allTrees = []
>     sql = 'create table if not exists categories%s (ID int(3) unsigned
> primary key auto_increment, Category varchar(40), Parent varchar(40));' %
> (store[0].upper() + store[1:])
>     cursor.execute(sql)
>     sql = 'create table if not exists categoriesRelationships%s (ID integer
> auto_increment primary key, Parent integer not null, foreign key (Parent)
> references categories%s (ID), Child integer not null, foreign key (Child)
> references categories%s (ID), check (Parent <> Child) );' %
> (store[0].upper() + store[1:], store[0].upper() + store[1:],
> store[0].upper() + store[1:])
>     cursor.execute(sql)
>     cursor.execute('select Category, Parent from categories%s;' %
> (store[0].upper() + store[1:]))
>     data = cursor.fetchall()
>     cursor.execute('select Category from categories%s order by Parent, ID;'
> % (store[0].upper() + store[1:]))
>     Categories = [itm[0] for itm in cursor] #untuple single column
>     if len(Categories) > 0:
>       cursor.execute('select Parent from categories%s order by Parent, ID;'
> % (store[0].upper() + store[1:]))
>       Parents = [itm[0] for itm in cursor]
>       MAXLEVEL = 15
>       # get top level
>       cursor.execute('select category from categories%s order by Category;'
> % (store[0].upper() + store[1:]))
>       theTree = expand(cursor.fetchall())
>       getChildren(theTree, store)
>       db.commit()
>       allTrees.append(theTree)
>       returnFlag = 'gotStuff'
>     else:
>       returnFlag = 'gotNoStuff'
>     finalTrees.append(printTree(allTrees))
>   
Possibly you wanted extend() here, not append.  As it stands now, you 
get a list of lists.
>   if returnFlag == 'gotStuff':
>     return finalTrees
>   else:
>     return ''
>
>
>   
Do you really mean to return a list if "gotStuff", and a string if not 
?  That puts a burden on your caller, and doesn't agree with the 
docstring you didn't write.

Incidentally, good naming would help to make the code easier to debug.  
This finalTrees and trees variables don't look to me like you intended 
them to be trees at all, but lists of tab-indented data.

DaveA




More information about the Python-list mailing list