欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

在Python 3的递归函数中:理解全局和非局部变量 - 重点在于你针对同一个可变对象的操作

最编程 2024-02-20 22:21:54
...

nonlocal的基本用法:

def outer():  
    num = 10  
    def inner():  
        nonlocal num   # nonlocal关键字声明  
        num = 100  
        print(num)  
    inner()  
    print(num)  
outer() 

运行结果:。两个num都是outer函数域里面的num,是同一个变量。

def outer():  
    num = 10  
    def inner():   
        num = 100  
        print(num)  
    inner()  
    print(num)  
outer() 

运行结果:。两个num不是同一个,outer有一个num变量,在inner的外部。inner也有个本地的num变量。

如何在递归函数中使用nonlocal:

def te(count):
    value = 0
    flag = [False]*count
    result_flag = [False]*count

    def recursion(i):
        nonlocal value,flag,result_flag
        value +=1
        flag[i] = True
        print(flag)
        if(flag == [True,True,False,False,False]):
            result_flag = flag
        for j in range(i+1,count):
            recursion(j)
        flag[i] = False
        
    for i in range(count):
        recursion(i)

    return (value,result_flag)


print(te(5))

 

运行结果:。可以看出来,递归一共调用31次。

 

其实也就是。比如C51,就是,从5个里面选一个出来的情况,只有5种:1,2,3,4,5。

其递归过程形如(没有画完,反正就是这个意思啦):

此递归程序,不需要设置递归的终点,因为二叉树的分支越来越少,到最后就没有分支了,递归也就到终点了。把上图的12345当成Ture,False的状态就行,有这个数,就代表这个数字上的位置为True,否则为False。

因为value,flag,result_flag,都是相对于递归函数的外部变量,但是这三个变量又都在te函数里,且刚好在recursion函数的外部,所以这里需要使用nonlocal。

以上这种递归程序的写法:在函数中定义真正的递归函数,然后在该函数中调用该递归函数。就可以达到,不需要定义全局变量,而且只给函数传一个参数,的效果。

引用变量赋值错误:

观察运行结果,返回的元祖,其中的result_flag应该为的,但是并没有,result_flag的每个元素都是False。其实,这里是引用型变量赋值造成的:

就好比flag是一条狗绳,牵在第一条狗身上,result_flag是另一条狗绳,牵在第二条狗身上。考虑flag的变化,虽然此变量在递归过程中一直在变化,但是递归结束后,flag必定都是False,因为在递归中,开始时有,结束时有,改变状态后,还会恢复状态。

执行了result_flag = flag,那么就把result_flag这条狗绳,也牵在了第一条狗身上,那么第二条狗没人管了,也就跑了(被垃圾回收了),但实际上,程序想要的效果是,同时存在两条狗,且返回第二条狗,第一条狗只是作为一个变量在递归中使用。

所以需要进行如下修改:

        if(flag == [True,True,False,False,False]):
            for m in range(len(flag)):
                result_flag[m] = flag[m]

运行结果:

此时,result_flag和flag,这两个引用实际指向的是,两个不同的变量。也就是,同时存在了两条狗。

或者重新构造一个新的list:

        if(flag == [True,True,False,False,False]):
            result_flag = [True,True,False,False,False]

 

 

 

推荐阅读