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