前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python的三个问题

Python的三个问题

作者头像
海纳
发布2018-03-02 14:52:48
6470
发布2018-03-02 14:52:48
举报
文章被收录于专栏:海纳周报海纳周报

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

代码语言:javascript
复制
 def foo(a = []):
    a.append(1)
    print a

foo()foo()

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

代码语言:javascript
复制
def foo():
    a = 1 
    def bar():
        a += 1
        print a    return bar 

func = foo()func()

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

代码语言:javascript
复制
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字节码是这样的:

代码语言:javascript
复制
LOAD_FAST aLOAD_CONST 1INPLACE_ADD

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

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

代码语言:javascript
复制
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的这个问题。所以就会出现上面所说的问题了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HinusWeekly 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档