简体   繁体   English

Python变量在递归函数中的for循环后丢失值

[英]Python variable loses value after for loop in recursive function

Is this a Python bug?这是一个Python错误吗? Variable loses value after for loop in a recursive function.变量在递归函数中的 for 循环后失去价值。 This is test code.这是测试代码。 I am really parsing XML.我真的在解析 XML。

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

In the program output below, I would always expect the Before for output to be identical to the After for output.在下面的程序输出中,我总是希望 Before 输出与 After 输出相同。

Program output:程序输出:

['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 version:蟒蛇版本:

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.

The confusing output is because the After for 0 output comes from a different recursive call of the function (not the same one as the Before for 0 output just above it).令人困惑的输出是因为After for 0输出来自函数的不同递归调用(与其上方的Before for 0输出不同)。

Here is a version of your function with some extra information to track the depth of the recursive calls:这是您的函数的一个版本,其中包含一些用于跟踪递归调用深度的额外信息:

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)

And here is the new output, which shows what I'm talking about:这是新的输出,它显示了我在说什么:

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']

This After is from the enclosing findversion call:这个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              <---
     ...

It is not a bug.这不是一个错误。 The variable aFlag is only local to the specific function call, because it is passed by value.变量 aFlag 只是特定函数调用的局部变量,因为它是按值传递的。 When your program prints 'Before for 1' it never enters the for loop, because aNode[2:] is empty (aNode only has two elements at that time).当您的程序打印 'Before for 1' 时,它永远不会进入 for 循环,因为 aNode[2:] 是空的(当时 aNode 只有两个元素)。 Thus, it never prints any 'After for' but returns immediately.因此,它从不打印任何 'After for' 而是立即返回。

The output will be more clear if you put the print statement 'After for' actually after the for loop instead of inside the for loop.如果将打印语句 'After for' 实际上放在 for 循环之后而不是在 for 循环内部,则输出将更加清晰。 Then the output will be consistent.然后输出将是一致的。

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

So in order to fix my program, I need to return the flag.所以为了修复我的程序,我需要返回标志。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM