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循环中变量的作用域的更多相关文章

  1. 注意for循环中变量的作用域-乾颐堂

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

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

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

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

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

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

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

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

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

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

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

  7. JavaScript 中变量、作用域和内存问题的学习

    这是我学习JavaScript的第二篇文章,之前做过几年的Java开发,发现JavaScript虽然也是面向对象的语言但是确实有很多不同之处.就本篇博客,主要学习总结一下最近学习到的JavaScrip ...

  8. if、while中变量的作用域问题

    我们知道,函数.类会改变当前变量的作用域.if,while等分支循环结构会继承外部作用域,即外部变量对分支循环结构内部可见. 但是C语言不支持if,while等分支循环结构内部作用域对外可见,而PHP ...

  9. JS中变量、作用域的本质,定义及使用方法

    全局作用域和局部作用域 全局作用域 局部作用域:函数作用域 全局作用域在全局和局部都可以访问到,局部作用域只能在局部被访问到 var name="cyy"; function fn ...

随机推荐

  1. 单源最短路——SPFA算法(Bellman-Ford算法队列优化)

    spfa的算法思想(动态逼近法):     设立一个先进先出的队列q用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路 ...

  2. Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题

    . 参考界面 : 携程app首页的广告栏, 使用ViewPager实现        自制页面效果图 : 源码下载地址: http://download.csdn.net/detail/han1202 ...

  3. UML建模语言入门-视图,事物,关系,通用机制

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 一. UML视图 1. Ration ...

  4. Alpha 冲刺3

    队名:日不落战队 安琪(队长) 今天完成的任务 组织第三次站立式会议. 完成了个人信息前端界面. 明天的计划 草稿箱前端界面. 个人信息扩展界面框架. 还剩下的任务 回收站前端界面. 信息修改前端界面 ...

  5. 【week2】结对编程-四则运算 及感想

    首先我要说一下,我得作业我尽力了,但是能力有限,还需练习. 四则运算,改进代码流程: 1.手动输入算式(属于中缀表达式) 2.将中缀表达式转化成后缀表达式 生成out数组 3.一个操作数栈,一个运算符 ...

  6. WASM

    WASM WebAssembly https://webassembly.org/ https://github.com/appcypher/awesome-wasm-langs https://me ...

  7. connectedSignal 简单使用

    import java.util.concurrent.CountDownLatch; public class CountDown { private static CountDownLatch c ...

  8. [CF888G]Xor-MST

    题目大意:给一个$n$个点的完全图,第$i$个点有点权$v_i$,一条边$x-y$的边权为$v_x\oplus v_y$,求最小生成树 题解:明显$Kruskal$和$Prim$都会$TLE$,有一种 ...

  9. 在Windows*上编译Tensorflow教程

    背景介绍 最简单的 Tensorflow 的安装方法是在 pip 一键式安装官方预编译好的包 pip install tensorflow 通常这种预编译的包的编译参数选择是为了最大兼容性而不是为了最 ...

  10. Cydia Substrate based DexDumper's weakness

    得益于Cydia Substrate框架,HOOK Native函数变得简单,也给脱壳带来方便. 像ijiami免费版,360,classes.dex被加密到so文件并运行时释放到内存,因此针对相关函 ...