注意for循环中变量的作用域
- for e in collections:
- pass
在for 循环里, 最后一个对象e一直存在在上下文中。就是在循环外面,接下来对e的引用仍然有效。
这里有个问题容易被忽略,如果在循环之前已经有一个同名对象存在,这个对象是被覆盖的。
如果在有代码感知的IDE中, IDE会提示变量是“被重新声明的”, 但运行时却不会出错。
for循环不是闭包,可以使用dis模块分解以下代码可以看到:
- x = 5
- for x 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)
注意for循环中变量的作用域的更多相关文章
- 注意for循环中变量的作用域-乾颐堂
1 2 for e in collections: pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循 ...
- for循环中变量的作用域问题
看下面这一行代码 for (let i = 0; i < 3; i++) { let i = 'abc' console.log(i) } // abc // abc // abc 从上面可以看 ...
- Python中变量的作用域(variable scope)
http://www.crifan.com/summary_python_variable_effective_scope/ 解释python中变量的作用域 示例: 1.代码版 #!/usr/bin/ ...
- C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期
全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...
- js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题)
js循环函数中的匿名函数和闭包问题(匿名函数要用循环中变量的问题) 一.总结 需要好好看下面代码 本质是因为匿名函数用到了循环中的变量,而普通方式访问的话,匿名函数的访问在循环之后,所以得到的i是循环 ...
- 关于while read line 循环中变量作用域的问题
前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据.于是用到了while read line 作为循环. 在制作文件计数器的时候发现了一个问题,在 ...
- JavaScript 中变量、作用域和内存问题的学习
这是我学习JavaScript的第二篇文章,之前做过几年的Java开发,发现JavaScript虽然也是面向对象的语言但是确实有很多不同之处.就本篇博客,主要学习总结一下最近学习到的JavaScrip ...
- if、while中变量的作用域问题
我们知道,函数.类会改变当前变量的作用域.if,while等分支循环结构会继承外部作用域,即外部变量对分支循环结构内部可见. 但是C语言不支持if,while等分支循环结构内部作用域对外可见,而PHP ...
- JS中变量、作用域的本质,定义及使用方法
全局作用域和局部作用域 全局作用域 局部作用域:函数作用域 全局作用域在全局和局部都可以访问到,局部作用域只能在局部被访问到 var name="cyy"; function fn ...
随机推荐
- 团队作业7——第二次项目冲刺(Beta版本)-第二篇
1.工作分工: 团队成员 分工 郭达22120 项目整合,后台代码 刘德培44060 数据库模块 石浩洋22061 前台界面优化 曾繁钦22056 前台界面优化.测试 孙斌22030 后台代码 2.燃 ...
- Ubuntu使用时遇到的问题
启动时显示System program problem detected 解决办法: 打开命令行窗口:Ctrl+Alt+T 执行命令:sudo gedit /etc/default/apport 把e ...
- iOS奔溃日志信息统计使用笔记
1.Bugly的集成很简单,直接一个pod就可以搞定 pod 'Bugly' 2.在官网上注册账号 3.初始化SDK 导入头文件 在工程的AppDelegate.m文件导入头文件 #import &l ...
- TCP系列21—重传—11、TLP
一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重 ...
- 在 visual studio 中添加 ILDASM 工具
先写下一般的用法,就是在 vs 中添加 ILDASM 工具. 添加步骤: 工具---->外部工具----->添加: 标题我一般取为 ILDASM,命令那一栏是要选择 ILDASM 的路径, ...
- KMP算法字符串查找子串
题目: 经典的KMP算法 分析: 和KMP算法对应的是BF算法,其中BF算法时间复杂度,最坏情况下可以达到O(n*m),而KMP算法的时间复杂度是O(n + m),所以,KMP算法效率高很多. 但是K ...
- RT-thread内核之线程调度器
一.前言 RT-Thread中提供的线程调度器是基于全抢占式优先级的调度,在系统中除了中断处理函数.调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自 ...
- Java序列简单使用
package javatest; import java.io.*; public class SerializableTest implements Serializable { public s ...
- Luogu3936 Coloring(模拟退火)
裸退火,每次交换两个格子即可.依旧不会调参,稍微抄了点参数并且把随机种子设成了一个神奇的数字终于过掉了. #include<iostream> #include<cstdio> ...
- axios post提交数据格式不对的问题
需要格式化一下 this.$http({ method: "post", url: "/chinacountry/index.php/home/Search/index& ...