2013-03-20 2 views
0

Является ли это ошибкой python? переменная теряет значение после цикла в рекурсивной функции. Это тестовый код. Я действительно разбираю xml.Python переменная теряет значение после цикла for в возвращающей функции

def findversion(aNode, aList, aFlag): 
    print "FindVersion ", aNode[0:1] 
    print "Findversion ", aFlag 
    if aNode[1].find('Software') != -1: 
     aFlag = 1 
     aList.append(aNode[1]) 
    if aFlag == 1 and aNode[0] == 'b': 
     aList.append(aNode[1]) 
    print "Before for ", aFlag 
    for elem in aNode[2:]: 
     print "After for ", aFlag 
     findversion(elem,aList,aFlag) 

node = ['td', 'Software version'] 
node2 = ['b', '1.2.3.4' ] 
node3 = [ 'td', ' ', node2 ] 
node4 = [ 'tr', ' ', node, node3 ] 
print node4 

myList = list() 
myInt = 0 
findversion(node4,myList,myInt) 
print "Main ",myList 

В выходном файле ниже, я бы всегда ожидал, что выход для выхода будет идентичным выходу для вывода.

выход программы

['tr', ' ', ['td', 'Software version'], ['td', ' ', ['b', '1.2.3.4']]] 
FindVersion ['tr'] 
Findversion 0 
Before for 0 
After for 0 
FindVersion ['td'] 
Findversion 0 

Before for 1 
After for 0 

FindVersion ['td'] 
Findversion 0 
Before for 0 
After for 0 
FindVersion ['b'] 
Findversion 0 
Before for 0 
Main ['Software version'] 

версия Python

Python 2.7.3 (default, Dec 18 2012, 13:50:09) 
[GCC 4.5.3] on cygwin 
Type "help", "copyright", "credits" or "license" for more information. 

ответ

0

Запутанной выход, потому что After for 0 выход поступает из другого рекурсивного вызова функции (не то же самое один как Before for 0 выход чуть выше Это).

Вот версия вашей функции с некоторой дополнительной информацией для отслеживания глубины рекурсивных вызовов:

def findversion(aNode, aList, aFlag, i=1): 
    print "FindVersion ", aNode[0:1], 'call:', i 
    print "Findversion ", aFlag, 'call:', i 
    if aNode[1].find('Software') != -1: 
     aFlag = 1 
     aList.append(aNode[1]) 
    if aFlag == 1 and aNode[0] == 'b': 
     aList.append(aNode[1]) 
    print "Before for ", aFlag, 'call:', i 
    for elem in aNode[2:]: 
     print "After for ", aFlag, 'call:', i 
     findversion(elem,aList,aFlag,i+1) 

А вот новый выход, который показывает, что я говорю о:

FindVersion ['tr'] call: 1 
Findversion 0 call: 1 
Before for 0 call: 1 
After for 0 call: 1 
FindVersion ['td'] call: 2 
Findversion 0 call: 2 
Before for 1 call: 2   # this is from the recursive call 
After for 0 call: 1   # this is from the original call 
FindVersion ['td'] call: 2 
Findversion 0 call: 2 
Before for 0 call: 2 
After for 0 call: 2 
FindVersion ['b'] call: 3 
Findversion 0 call: 3 
Before for 0 call: 3 
Main ['Software version'] 
0

Это After от вмещающего findversion вызова:

... 
print Before for 0 
start iterating over aNode 
    first td: 
    print After for 0 
    call findversion 
     print FindVersion ['td'] 
     print Findversion 0 
     find Software, set aFlag = 1 
     print Before for 1   <--- 
     start iterating over aNode 
     it's empty 
    second td: 
    print After for 0    <--- 
    ... 
0

Это не ошибка. Переменная aFlag является только локальной для конкретного вызова функции, потому что она передается по значению. Когда ваша программа печатает «Before for 1», она никогда не входит в цикл for, потому что aNode [2:] пуст (в то время у aNode только два элемента). Таким образом, он никогда не печатает «After for», но сразу возвращается.

Выход будет более понятным, если вы положите оператор печати «After for» на самом деле после цикла for, а не внутри цикла for. Тогда выход будет согласованным.

print "Before for ", aFlag 
for elem in aNode[2:]:  
    findversion(elem,aList,aFlag) 
print "After for ", aFlag 
0

Поэтому, чтобы исправить мою программу, мне нужно вернуть флаг.

def findversion(aNode, aList, aFlag): 
    print "FindVersion ", aNode[0:1] 
    print "Findversion ", aFlag 
    if aNode[1].find('Software') != -1: 
     aFlag = 1 
     aList.append(aNode[1]) 
    if aFlag == 1 and aNode[0] == 'b': 
     aList.append(aNode[1]) 
     aFlag = 0 
    print "Before for ", aFlag 
    for elem in aNode[2:]: 
     print "After for ", aFlag 
     aFlag = findversion(elem,aList,aFlag) 
    return aFlag 
Смежные вопросы