UnboundLocalError,探讨Python中的绑定
绑定
将python闭包之前,先梳理一下闭包中的绑定操作。
先看看2个相关的错误 NameError 和UnboundLocalError
When a name is not found at all, a
NameErrorexception is raised. If the name refers to a local variable that has not been bound, aUnboundLocalErrorexception is raised.UnboundLocalErroris a subclass ofNameError.
NameError比较好理解,即引用未定义,例如
fun1()
def fun1():
pass
但是UnboundLocalError却比较隐晦,意思是引用变量未绑定,注意这里的变量可能是已经定义了的。
**If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. **This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
下面来看看关于这种错误的隐晦bug。
def outer_func():
loc_var = "local variable"
def inner_func():
loc_var += " in inner func"
return loc_var
return inner_func
clo_func = outer_func()
clo_func()
#UnboundLocalError: local variable 'loc_var' referenced before assignment
程序在执行clo_func()的时候出了问题。
注意语句loc_var += " in inner func"可以看作loc_var = loc_var + " in inner func", 而在求取算式loc_var + " in inner func"的时候需要变量loc_var的值,而变量loc_var在函数inner_func内是有定义的,即loc_var += " in inner func", 因此inner_func会去引用该值,但是inner_func的loc_var却没有完成绑定,因此出现了UnboundLocalError错误,有点类似递归死循环。
由此可见,python中总是优先引用自身代码块内出现的变量,不管先后次序。
注意这里是不管先后次序,因此可能引发UnboundLocalError
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block.
再举一个类似的例子
import sys
def add_path(new_path):
path_list = sys.path
if new_path not in path_list:
import sys
sys.path.append(new_path)
add_path('./')
此处path_list = sys.path 会引用第2个 import sys 而不是第一个, 由此导致了引用未绑定,因为sys被当成了还没有import。
bind name:下面的操作均可视为绑定操作
- 函数的形参
- import声明
- 类和函数的定义
- 赋值操作
- for循环首标
- 异常捕获中相关的赋值变量
还有一些关于UnboundLocalError的其他例子,如下
1 def get_select_desc(name, flag, is_format = True):
2 if flag:
3 sel_res = 'Do select name = %s' % name
4 return sel_res if is_format else name
5
6 get_select_desc('Error', False, True)
这种错误在编译的时候不会出错,但是在运行某些例子的时候就会出现UnboundLocalError。
那如何避免这种错误呢?我觉得可以注意以下几点
当局部变量与全局变量重名时
当通过函数参数来选择是否绑定变量时
这种错误和诸如C, C++等其他语言有较大差别,我觉得可能是因为在这些语言中变量的定义是明确的,如int i = 1; 。而在python中却不需要明确定义变量,因此python的每一条赋值语句在某种程度上可以说都是一次定义。但有时候这样子很不方便,于是python里也有了相应的语法,nonlocal与global定义, 但是注意nonlocal是python3的语法
参考 https://www.cnblogs.com/yssjun/p/9873689.html
UnboundLocalError,探讨Python中的绑定的更多相关文章
- 简单探讨python中的语句和语法
python程序结构 python"一切皆对象",这是接触python听到最多的总结了.在python中最基层的单位应该就是对象了,对象需要靠表达式建立处理,而表达式往往存在于语句 ...
- python中绑定码云仓库
1.File——Settings——Version Control——Git——输入git安装路径下bin下的git.exe路径——点击后面的Test测试一下,弹出版本点击ok即可 2.点击工具栏中的 ...
- python 中使用 global 引发了莫名其妙的问题
哪里出问题了 python 中,使用 global 会将全局变量设为本函数可用.同时,在函数内部访问变量会先本地再全局. 在嵌套函数中,使用 global 会产生不合常理的行为. 上代码: In [9 ...
- Python的名字绑定
Python的名字绑定 在Python中,对象是通过名字进行关联和引用的.Python通过名字绑定操作来引入名字. Python中的所谓的代码块就是一段作为执行单元的程序.比如:模块.函数.类定义.在 ...
- Python中的属性管理
Python管 理属性的方法一般有三种:操作符重载(即,__getattr__.__setattr__.__delattr__和 __getattribute__,有点类似于C++中的重载操作符).p ...
- 可爱的 Python : Python中函数式编程,第二部分
英文原文:Charming Python: Functional programming in Python, Part 2,翻译:开源中国 摘要: 本专栏继续让David对Python中的函数式编 ...
- 谈谈自己的理解:python中闭包,闭包的实质
闭包这个概念好难理解,身边朋友们好多都稀里糊涂的,稀里糊涂的林老冷希望写下这篇文章能够对稀里糊涂的伙伴们有一些帮助~ 请大家跟我理解一下,如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内 ...
- Python中的作用域及global用法
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的. 函数定义了本地作用域,而模块定义的是全局作用域. 如果想要在函数内定义全局作用域,需要加上global修饰符. 变量名解析:LE ...
- python中对变量的作用域LEGB、闭包、装饰器基本理解
一.作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量 ...
随机推荐
- 有关于python内置函数exec和eval一些见解笔记
eval是将函数内的字符串以计算式的方式进行计算并给与外部一个值. 例: a=eval('1+1') print(a) >>>>2 但是如果出现在函数内部字符串中进行赋值会抛出 ...
- requests.exceptions.SSLError报错
requests.exceptions.SSLError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries excee ...
- 初识JVM:(一)JVM工作原理和流程
本文主要参考:http://blog.csdn.net/CSDN_980979768/article/details/47281037?locationNum=7&fps=1 声明:主要用于个 ...
- css中:overflow:hidden清除浮动的原理
要想彻底清除浮动的影响,适合的属性不是 clear 而是 overflow. 一般使用 overflow:hidden,利用 BFC 的“结界”特性彻底解决浮动对外部或兄弟元素的影响. 1. 前言: ...
- .tar.xz文件的创建和解压
创建tar.xz文件:只要先 tar cvf xxx.tar xxx/ 这样创建xxx.tar文件先,然后使用 xz -z xxx.tar 来将 xxx.tar压缩成为 xxx.tar.xz 解压ta ...
- EPX Studio开发环境介绍
相信用过Delphi的人,都很清楚FastScript,EPX Studio就是以FastScript为编程基础语言,由于FastScript支持类似于Delphi的Pascal语法,因此EPX St ...
- window 查看端口 杀端口
最近写项目,总是出现端口被占用的问题,原来傻傻的把电脑重启一下,终于有一天受不了了,想要想办法解决.刚开始从网上找了好多教程,发现不行.开始自己尝试,终于,成功的将占用端口的进程杀掉.在此记录下过程( ...
- 控制游戏/app使用期限/过期,证书有效期,弹出公告支持离线使用/后端控制,支持Swift、Objective-C集成非常简单,永久免费框架
CertCheck.framework (for iOS) 只能运行于真机上,切勿在模拟器上使用 这是一个控制游戏/app使用期限(到设定的时间无法打开app),或发布弹出公告永久免费的框架,可以全版 ...
- MySQL----DQL(查询数据库表中数据)
##DQL:查询表中的记录 1.语法: select 字段列名 from 表名列表 where 条件列表 group by 分组字段 having 分组之后的条件 order by 排序 lim ...
- MySql InnoDB中的锁研究
# MySql InnoDB中的锁研究 ## 1.InnoDB中有哪些锁### 1. 共享和排他(独占)锁(Shared and Exclusive Locks) InnoDB实现标准的行级锁定,其中 ...