您的不理解和惊讶,就像许多学习 Python 的人一样(在 stackoverflow.com 上使用“赋值前引用”表达式进行研究),我认为是因为文档有时写得不好。
这个错误的解释在这里:
如果名称绑定操作发生在代码块中的任何位置,则所有
块内名称的使用被视为对
当前块。这可能会在名称中使用时导致错误
在绑定之前阻塞。这个规则很微妙。 Python缺乏
声明并允许名称绑定操作在任何地方发生
在一个代码块内。代码块的局部变量可以是
通过扫描块的整个文本来确定名称绑定
操作。
http://docs.python.org/2/reference/executionmodel.html
在我看来,这段摘录错误地表达了执行代码时所执行的操作:
说“可以通过扫描确定”是骗人的,给人的印象是这种扫描是可选的。
虽然我从未读过任何关于这一点的内容可以证实我的观点,但我个人认为:
- 事实上,这种扫描IS总是执行,这不是一个选项
- 更重要的是,此扫描是在在块定义的可调用对象的任何调用之前完成的
.
确实,首先要理解一个重要的概念:
可调用对象的定义是在对象被调用之前完成的
必须意识到“定义”一词是模棱两可的,因为它可以通过两种方式来理解:
1/ 定义 = “定义”某些东西的脚本中的代码块
2/ 定义 = 在执行脚本的时刻执行此代码块以创建定义的可调用对象
我的这些断言基于:
块是作为一个单元执行的一段 Python程序文本。
以下是块:模块、函数体和类
定义。
http://docs.python.org/2/reference/executionmodel.html
.
函数定义定义了用户定义的函数对象 (...)
函数定义 [意义 1] 是一个可执行语句。它的执行绑定
当前本地命名空间中的函数名到函数对象
(...)
函数定义[意义2]不执行函数体;
this 仅在调用函数时执行。
http://docs.python.org/2/reference/compound_stmts.html#function-definitions
.
A function definition defines a user-defined function object: 好漂亮的重言式!这句话说明了什么。我认为分析以下内容更有用:
[意义 1] 那里,“定义”的意思是“定义的代码块(=文本)”
[sens 2] 那里,“定义”的意思是“定义代码块的执行”;文本(定义意义 1)不执行任何操作,它作为文本被动地存在......
你看到“定义”这个名字是模棱两可的,而且文档有时写得不好.....
最后一个提取涉及函数定义,但这些概念显然可以扩展到类,其他可调用对象。类也由代码块定义,然后它们也存在这两个步骤:定义(意义 2= 执行定义代码块)然后调用。
.
所以我的主张是,我认为扫描可调用对象中的标识符并确定它们的范围是在执行代码块 [= 定义意义 1] 的那一刻执行的,这个执行是所谓的“定义”[意义 2]。
这就是我想指出的关键点。
.
PS:在上述文档摘录中使用术语“变量”是令人遗憾的,因为在 Python 中使用“变量”是另一个高度含糊的术语。
令人遗憾的证据是,OP 提出了他的问题,比较 Java 中发生的事情和 Python 中发生的事情。
如果在基本官方文档中的某个地方有一个可靠的解释,即在 Python 中编码器无法访问充当“内容可以更改的内存块”的实体,那么这种混淆应该很少发生。
但那是另一回事了