Python的三个问题

时间:2022-05-02
本文章向大家介绍Python的三个问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

第一,以下程序的执行结果是什么?

 def foo(a = []):
    a.append(1)
    print a

foo()foo()

第二,以下程序的执行结果是什么?

def foo():
    a = 1 
    def bar():
        a += 1
        print a    return bar 

func = foo()func()

第三,以下程序的执行结果是什么?

l = [x for x in xrange(10)]print x
d = {x : 2 * x for x in xrange(5)}print x

第一题的答案是

[1]

[1, 1]

这是因为,在Python中,Function是一种Object,所以foo函数其实是一个FunctionObject,它的默认参数是与这个Object绑定在一起的。所以,每次调用,所使用的参数a其实是同一个list对象。

第二题,运行会出现traceback。

出现这个的原因是因为Python编译器写得太简单了。它并没有合理地处理所有变量的scope。我们希望产生一个闭包,在bar方法里可以看得到它外面的变量。但是,实际上,我们得到的Python字节码是这样的:

LOAD_FAST aLOAD_CONST 1INPLACE_ADD

问题就出在这个LOAD_FAST上,我们知道,正确的闭包所使用的字节码其实应该是LOAD_CLOSURE。但在这里,因为在bar方法里,对a进行了赋值,所以编译器就把a当做了局部变量。访问一个未定义的局部变量当然就是错的了。

要想在Python里使用闭包,正确的做法是:

def foo():
    a = [1] 
    def bar():
        a[0] += 1
        print a[0]

    return bar 

func = foo()func()func()

第三题,在2.7里,可以正确运行。结果是9, 9。

在2.6的时代,只支持列表推导式,字典推导式还没有得到支持。所以,如果你在2.6上运行这段程序,是会报错的。其实,在2.6的列表推导式的实现中,有一个设计缺陷,那就是循环变量x会污染外层的命名空间。也就是说,我执行完列表推导式以后,x 会进到程序的locals表里。而在2.7里,在实现字典表达式的时候,却又把这个循环变量做为局部变量处理了。所以离开了推导式,这个x就消失不见了。同时,2.7没有修复2.6的这个问题。所以就会出现上面所说的问题了。