Python print语句如何创建局部变量
问题在这篇文章的末尾 第一个代码段:空的局部变量字典Python print语句如何创建局部变量,python,python-internals,Python,Python Internals,问题在这篇文章的末尾 第一个代码段:空的局部变量字典 def outer(): x = 1 def inner(): print "Local variables: %s" % locals() return inner() print outer() 输出: 局部变量:{} 第二个代码段:打印内部()函数并创建局部变量条目 def outer(): x = 1 def inner(): print x p
def outer():
x = 1
def inner():
print "Local variables: %s" % locals()
return inner()
print outer()
输出:
局部变量:{}
第二个代码段:打印内部()函数并创建局部变量条目
def outer():
x = 1
def inner():
print x
print "Local variables: %s" % locals()
return inner()
print outer()
输出:
1
Local variables: {'x': 1}
>>> outer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in outer
File "<stdin>", line 4, in inner
UnboundLocalError: local variable 'x' referenced before assignment
>>>
第三个代码段:从内部函数中删除x:
def outer():
x = 1
def inner():
print x
print "Local variables: %s" % locals()
del x
return inner()
print outer()
输出:
1
Local variables: {'x': 1}
>>> outer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in outer
File "<stdin>", line 4, in inner
UnboundLocalError: local variable 'x' referenced before assignment
>>>
>>>外部()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第7行,在外部
文件“”,第4行,在内部
UnboundLocalError:赋值前引用了局部变量“x”
>>>
问题:
有人能帮我理解一下吗。在Python中,除非您在函数中的任何地方(通过
global
语句或nonlocal
语句)另外指定,否则如果您修改它(赋值给它,del
它,等等),变量就在locals
中*
在第一个代码段中,您从未修改过x
,甚至从未访问过它,因此它不是本地的。事实上,它根本不存在。那很容易
第二个版本很棘手x
不是internal
本地的,因为您不在internal
中修改它。因此,Python开始寻找它,一个作用域一个作用域向外移动,直到找到一个包含该变量的作用域。它在outer
中作为局部变量找到它。这意味着它是internal
中的闭包变量或自由变量。因为函数包括闭包变量和局部变量,所以您可以看到它
第三个版本,通过执行del x
,使x
成为内部的本地
**因此,它出现在本地
中。但是,您尝试打印
它,而没有为其分配任何内容,因此还没有值。因此,您会得到一个取消绑定的LocalError
一般来说,一旦您理解了Python试图在这里实现的基本思想,通常很明显您拥有什么类型的变量。但如果不清楚的话,详细规则将在中定义
如果您想了解闭包在封面下是如何工作的,可以从检查函数对象开始。试试这个:
def outer():
x = 1
def inner():
print x
print "Local variables: %s" % locals()
return inner
inner = outer()
print inner.func_closure
print inner.func_code.co_freevars
print outer.func_code.co_cellvars
模块文档列出了函数
、代码
和其他“隐藏”对象的所有重要成员
使用模块查看外部
和内部
的字节码也可能会有所帮助。***例如,如果您运行,您将看到本地的LOAD\u FAST
,单元格的LOAD\u DEREF
,全局的LOAD\u GLOBAL
但是,如果您真的想了解所有这些是如何工作的,那么Eli Bendersky的“Python内部构件”博客上的系列文章将非常好地涵盖所有内容。(感谢Ashwini Chaudhary找到它并在评论中指出。)
*这是在编译时检查的,而不是在执行时检查的,因此尝试将其与(例如,
exec
混淆会成功地混淆Python和您自己
**请注意,del
同时计为修改和访问。这可能令人惊讶,但您可以看到,def foo():del x
将引发UnboundLocalError
,因为del
使x
成为本地,而同样的del
无法找到值
***…假设您使用的是使用CPython样式字节码的Python实现,例如CPython本身(当然)或PyPy。Python通过查看编译时如何使用变量来支持嵌套作用域。您在函数中指定的变量(或在函数中使用
导入
绑定的变量)被视为本地变量,其他所有变量都是非本地变量。尝试删除变量时,也会将其标记为局部变量
在父作用域中搜索非本地名称,如果未找到,则视为全局名称
在第二个示例中,x
引用父范围中的名称。您没有分配给它,因此它是一个嵌套名称,可以在本地名称空间中看到。它实际上不是一个本地名称,而是一个自由变量;它的值取自父范围
在上一个示例中,您尝试删除x
,使其成为本地名称。在分配任何内容之前尝试引用它会导致异常
所有这些都记录在Python参考文档中。具体而言:
在代码块中使用名称时,将使用最近的
封闭范围。代码块可见的所有此类作用域的集合是
称为块的环境
如果名称绑定在块中,则它是该块的局部变量。
如果名称在模块级别绑定,则它是一个全局变量。(修订)
模块代码块的变量为局部变量和全局变量。)如果
变量在代码块中使用,但未在代码块中定义,它是一个自由变量
变数
以下构造绑定名称:函数的形式参数,
import
语句、类和函数定义(它们绑定
定义块中的类或函数名),以及
标识符,如果发生在分配中,则在
的第二个位置,除了
子句标题或在带
陈述表单的from的import
语句。。。导入*
binds
导入模块中定义的所有名称,以开头的名称除外
下划线。此表格只能在模块级使用
出现在del
语句中的目标也被认为是绑定的
这就是目的(尽管实际的语义是解除名称绑定)。信息技术
取消绑定封闭范围引用的名称是非法的;
th