1
2
for in collections:
    pass

在for 循环里, 最后一个对象e一直存在在上下文中。就是在循环外面,接下来对e的引用仍然有效。

这里有个问题容易被忽略,如果在循环之前已经有一个同名对象存在,这个对象是被覆盖的。

如果在有代码感知的IDE中, IDE会提示变量是“被重新声明的”, 但运行时却不会出错。

for循环不是闭包,可以使用dis模块分解以下代码可以看到:

1
2
3
4
= 5
for in range(10):
    pass
print x

将代码保存到test.py文件,运行python -m dis test.py

C:\Users\Patrick\Desktop>python -m dis test.py

1           0 LOAD_CONST               0 (5)

3 STORE_NAME               0 (x)

3           6 SETUP_LOOP              20 (to 29)

9 LOAD_NAME                1 (range)

12 LOAD_CONST               1 (10)

15 CALL_FUNCTION            1

18 GET_ITER

>>   19 FOR_ITER                 6 (to 28)

22 STORE_NAME               0 (x)

4          25 JUMP_ABSOLUTE           19

>>   28 POP_BLOCK

6     >>   29 LOAD_NAME                0 (x)

32 PRINT_ITEM

33 PRINT_NEWLINE

34 LOAD_CONST               2 (None)

37 RETURN_VALUE

在其他语言里,for循环的初始化变量对于上下文同样是可见的,比如java, 因为java是强类型的语言, 如果重新声明已存在的变量IDE会提示错误, 当然不同通过编译。

通常在python编程中(可能是大多数的动态语言),有时即使声明了同名的变量,程序没有出现明显的错误,但是一旦出错,错误很难被发现。所以要避免与for循环中的变量重名。

在使用python模板语言编码时尤其如此。代码编辑器没有提示,不会发现错误在哪里。这个是我碰到的极其怪异的一个例子。为什么说怪异,因为逻辑上没有任何问题。

在一个页面模板里面,当handler调用这个模板时,同时传递了两个对象(从handler中,我使用tornado),一个page对象和一个pages列表。我的顺序是这样的:

<!-- 用page对象 -->

<label>{{ page.name if page else ''}}</label>

<!-- 用pages对象 -->

<label>Parent Page

<select name="parent_id">

{% if pages %}

{% for page in pages%}

<option value="{{ page.id}}">{{page.name}}</option>

{% end %}

{% end %}

<option value="">None</option>

</select>

</label>

<!-- 然后又page -->

<div>{{ page.markdown if page else ''}}</div>

问题来了,在运行的时候出错了,提示在 <label>{{ page.name if page else ''}}</label> 中错误page referenced before assignment.

晕死了, 找了一晚上的错,最后在把for循环中page的名字改为_page才运行了。

在模板调用过程里,模板语言也是被翻译到python字节码,并按行解析和出,所以根本没有逻辑,不知道是tornado模板语言的bug。

所以注意变量名。

总之我认为tornado的exception trace非常不友好。

Python中变量的作用域搜索顺序:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

http://www.qytang.com/
http://www.qytang.com/cn/list/29/

http://www.qytang.com/cn/list/28/446.htm
http://www.qytang.com/cn/list/28/445.htm
http://www.qytang.com/cn/list/28/444.htm
http://www.qytang.com/cn/list/28/442.htm
http://www.qytang.com/cn/list/28/440.htm
http://www.qytang.com/cn/list/28/437.htm
http://www.qytang.com/cn/list/28/435.htm
http://www.qytang.com/cn/list/28/434.htm
http://www.qytang.com/cn/list/28/433.htm
http://www.qytang.com/cn/list/28/431.htm
http://www.qytang.com/cn/list/28/328.htm
http://www.qytang.com/cn/list/28/326.htm
http://www.qytang.com/cn/list/28/429.htm

注意for循环中变量的作用域-乾颐堂的更多相关文章

  1. 注意for循环中变量的作用域

    for e in collections: pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循环之前已经有一个 ...

  2. nginx内置变量详解-乾颐堂

    nginx的配置文件中可以使用的内置变量以美元符$开始,也有人叫全局变量.其中,部分预定义的变量的值是可以改变的. $arg_PARAMETER 这个变量值为:GET请求中变量名PARAMETER参数 ...

  3. for循环中变量的作用域问题

    看下面这一行代码 for (let i = 0; i < 3; i++) { let i = 'abc' console.log(i) } // abc // abc // abc 从上面可以看 ...

  4. Django中的元类-乾颐堂

    看Django(1.6)的Form相关源代码时比较迷惑,于是节选了django.forms.forms.py中的几个代码片段来分析Django中是怎么使用元类的: 1 2 3 4 5 6 7 8 9 ...

  5. Python中变量的作用域(variable scope)

    http://www.crifan.com/summary_python_variable_effective_scope/ 解释python中变量的作用域 示例: 1.代码版 #!/usr/bin/ ...

  6. C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期

    全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...

  7. js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题)

    js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题) 一.总结 需要好好看下面代码 本质是因为匿名函数用到了循环中的变量,而普通方式访问的话,匿名函数的访问在循环之后,所以得到的i是循环 ...

  8. 乾颐堂7月HCIE、CCIE通过名单

    拼多多都上市了,现在很多培训机构也流行公用一张PASS了,山寨总是山寨的,不脚踏实地总是欺骗自己7月(自然月)乾颐堂通过22名学员,每个考试日通过一名HCIE.CCIE 转载于:https://blo ...

  9. 关于while read line 循环中变量作用域的问题

    前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据.于是用到了while read line 作为循环. 在制作文件计数器的时候发现了一个问题,在 ...

随机推荐

  1. Unit04: JSP基本语法 、 JSP运行原理

    Unit04: JSP基本语法 . JSP运行原理 hello.jsp <%@page pageEncoding="utf-8"%> <!doctype html ...

  2. advapi32.dll kernel32.dll 中的两套注册表API

    日前遇到一件事:WebBrowser中的网页会用到一个“大众”ActiveX控件,为了保证兼容性以及和其它程序互不干扰,我们采用这样一种方案: 1. 我们的软件会自带该控件: 2. 如果系统中已注册有 ...

  3. 多分类下的ROC曲线和AUC

    本文主要介绍一下多分类下的ROC曲线绘制和AUC计算,并以鸢尾花数据为例,简单用python进行一下说明.如果对ROC和AUC二分类下的概念不是很了解,可以先参考下这篇文章:http://blog.c ...

  4. 手势GestureDetector.OnGestureListener事件的调起

    @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionE ...

  5. 搞点事情,使用node搭建反向代理

    导语 最近有个需求,需要对业务管理后台的操作记录进行上报.一般这种上报需求都是又后台同学来做比较合适的.但是因为后台人力的原因.这个工作落到了我这个小前端的头上.这里记录下做这个需求踩的一些坑. 一. ...

  6. 跟我学算法-tensorflow 实现线性拟合

    TensorFlow™ 是一个开放源代码软件库,用于进行高性能数值计算.借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU.GPU.TPU)和设备(桌面设备.服务器集群.移动设备.边缘设 ...

  7. 解读linux中用户密码规则及忘记root口令的破解(思路)

    linux当中,用户名和密码表对应关系放在/etc/passwd中,如: root:x:0:0:root:/root:/bin/bash 格式代表意义分别为 用户名:密码:用户id:组id:用户描述 ...

  8. Volatile关键字以及线程的内存可见性问题

    一.Volatile关键字 作用: 当多个线程进行操作共享数据时,可以保证内存中的数据可见,即为一个线程对数据的修改对另外一个线程来说是可见的.相较于 synchronized 是一种较为轻量级的同步 ...

  9. 深入探究jvm之类装载器

    一.class装载验证流程 1.加载 1).取得类的二进制流. 2).转为方法区数据结构. 3).在Java堆中生成对应的java.lang.Class对象. 2.链接--验证(目的:保证Class流 ...

  10. SPI子系统分析之一:框架

    内核版本:3.9.5 SPI子系统概述: 一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号. SPI总线上有两类设备: 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式M ...