如何在python中定义自由变量?

2024-05-19 06:22:43 发布

您现在位置:Python中文网/ 问答频道 /正文

来自python doc局部/全局/自由变量定义:

If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.


代码1:

>>> x = 0
>>> def foo():
...   print(x)
...   print(locals())
... 
>>> foo()
0
{}

代码2:

>>> def bar():
...   x = 1
...   def foo():
...     print(x)
...     print(locals())
...   foo()
... 
>>> bar()
1
{'x':1}

当自由变量在函数块中调用而不是在类块中调用时,由locals()返回。


Code 1中,x是一个全局变量,它在foo()中使用但未定义。
但是它不是一个自由变量,因为它不是由locals()返回的。
我想不是医生说的。是否有自由变量的技术定义?


Tags: ofnameinif定义fooislocal
3条回答

据我所知,文档中的自由变量确实有点模棱两可。有自由全局变量被视为普通全局变量和词汇绑定自由变量。Eli Bendersky sum在一个blog post on symbol tables中很好地总结了一下:

Unfortunately, there's a shorthand in the core of Python that may initially confuse readers as to exactly what constitutes a "free" variable. Fortunately, it's a very slight confusion that's easy to put in order. The execution model reference says:

If a variable is used in a code block but not defined there, it is a free variable.

这与formal definition一致。然而,在源代码中,“free”实际上用作“词汇绑定的自由变量”(即在封闭范围内找到绑定的变量)的缩写,而“global”则用于引用所有剩余的自由变量。因此,在阅读CPython源代码时,一定要记住,完整的自由变量集既包括专门标记为“free”的变量,也包括标记为“global”的变量。

因此,为了避免混淆,当我想将CPython中实际处理的变量称为自由变量时,我会说“词汇绑定”。

(强调我的)

之所以使用这个速记,可能是因为当您有一个全局自由变量时,所发出的字节码实际上没有任何变化。如果一个global变量是“free”,或者如果它不是free,那么在这两种情况下查找该名称时都会使用LOAD_GLOBAL。所以全局自由变量并没有那么特别。

另一方面,词汇绑定变量被特殊处理并封装在^{}对象中,对象是词汇绑定自由变量的存储空间,位于给定函数的__closure__属性中。为此创建了一个特殊的^{}指令,用于检查存在自由变量的单元格。LOAD_DEREF指令的说明是:

LOAD_DEREF(i)

Loads the cell contained in slot i of the cell and free variable storage

因此,在Python中,只有当一个对象的定义(即静态)嵌套在另一个对象的定义(即状态)中时,无变量才作为一个概念起作用。

自由变量定义:已使用,但既不是全局变量也不是绑定变量

例如:

  1. x在代码1中不是自由的,因为它是一个全局变量。
  2. x在代码2中的bar()中不可用,因为它是一个绑定的变量。
  3. xfoo()中是免费的。

Python之所以做出这种区分是因为闭包。自由变量在当前环境中没有定义,即局部变量的集合,也不是全局变量!因此,它必须在别处定义。这就是闭包的概念。在代码2中,foo()bar()中定义的x上关闭。Python使用词法范围。这意味着,解释器可以通过查看代码来确定范围。

例如:xfoo()中被称为变量,因为foo()bar()包围,而xbar()绑定。

Python专门处理全局范围。可以将全局范围视为最外层的范围,但这并不是因为性能的原因(我认为)。因此x不可能同时是自由的全局的

豁免

生活并不是那么简单。存在自由全局变量。Python docs(执行模型)说:

The global statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains a global statement, the free variable is treated as a global.

>>> x = 42
>>> def foo():
...   global x
...   def baz():
...     print(x)
...     print(locals())
...   baz()
... 
>>> foo()
42
{}

我自己也不知道。我们都是来学习的。

变量只是用来存储值的保留内存位置。这意味着当你创建一个变量时,你会在内存中保留一些空间。

根据变量的数据类型,解释器分配内存并决定哪些可以存储在保留内存中。因此,通过为变量分配不同的数据类型,可以在这些变量中存储整数、小数或字符。

给变量赋值

Python变量不需要显式声明来保留内存空间。将值赋给变量时,声明会自动发生。等号(=)用于给变量赋值。

相关问题 更多 >

    热门问题