如果你经常遇到下面的报错,‘local variable ‘a’ referenced before assignment’,建议花几分钟看完这篇文章。
要解决这个问题,需要搞明白python中变量的作用域。
什么是作用域
什么是作用域呢?python在创建、改变、查找变量名时,都是在一个保存变量名的空间内进行,这个空间就是命名空间,也称作用域。
python包含以下4种作用域:
- L(local)局部作用域
局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。
- E(enclosing)嵌套作用域或称为闭包作用域
E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。
- G(global)全局作用域
即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。
注意:全局作用域的作用范围仅限于单个模块文件内
- B(built-in)内置作用域
系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。
作用域的优先级
python中对作用域的优先级,体现在LEGB法则:
当在函数中使用未确定的变量名时,Python会按照优先级依次搜索4个作用域,以此来确定该变量名的意义。
(L)首先搜索局部作用域
(E)之后是上一层嵌套结构中def或lambda函数的嵌套作用域
(G)之后是全局作用域
(B)最后是内置作用域
按这个查找原则,在第一处找到的地方停止。如果没有找到,则会出发NameError错误。
作用域的优先级:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域