Python循环中的local变量绑定问题

考虑以下代码

func_list = []

def foo(d):
    print 'num', num
    _num = num
    return d['level'] > _num

def get_f(num):
    _num = num
    def bar(d):
        print 'num', _num
        return d['level'] > _num
    return bar

for num in (30, 60):
    level_func = foo
    #level_func = get_f(num)
    func_list.append(level_func)


d = {'level': 40}

for f in func_list:
    print f(d)

当level_func是foo时,两次调用都会输出num=60,而level_func = get_f(num),才会输出期望的num=30, num=60。

原因是循环中level_func都绑定了同一个local变量num,而循环结束后,变量num的值为60,所以输出都是60。而get_f里面定义了_num=num,bar函数的_num是指向get_f里面所定义的_num,这是因为Python里def定义函数创造了一个新的variable scope;循环两次,get_f里形成闭包,保存了循环当时的值。

但每次都要定义一个辅助函数(上例的get_f)总觉得麻烦,如何解决?其实可以利用Python的一个“坑”
代码:

level_func = lambda d, num=num: return d['level'] > num

原理就是利用Python函数默认参数是在定义时绑定。

具体的差别可以用过dis模块来打印函数的bytecode查看。


  • muxueqz

    hi,你的博客RSS貌似有问题哦,http://feedvalidator.org/check.cgi?url=http%3A%2F%2Fblog.lzhaohao.info%2Ffeed%2F

    • ukessi

      感谢反馈,已修正。

      • muxueqz

        这才发现我留言了两次。。。现在貌似好了