我有一个非常简单的例子:#!/usr/bin/env python
#a() # 1: NameError: name 'a' is not defined
#b() # 1: NameError: name 'b' is not defined
#c() # 1: NameError: name 'c' is not defined
def a():
c() # note the forward use here...
#a() #2: NameError: global name 'c' is not defined
#b() #2: NameError: name 'b' is not defined
#c() #2: NameError: name 'c' is not defined
def b():
a()
#a() #3: NameError: global name 'c' is not defined
#b() #3: NameError: global name 'c' is not defined
#c() #3: NameError: name 'c' is not defined
def c():
pass
a() # these all work OK...
b()
c()
我在Python源文件中按字母顺序定义了3个名为a()、b()和c()的函数。每个函数定义的主体是对其他函数之一的调用。从我的注释可以看出,我必须在这些函数的定义之下(在文本文件中)对其中的第一个函数进行初始调用,但不一定需要在调用它的另一个函数之上定义函数。
当然,在所有函数定义(在Python和许多其他语言中)下面都有第一个可执行代码似乎是一种常见的做法,现在我明白了原因。在C和C++中,头文件负责处理这个问题。在Pascal中,在使用名称定义之前必须有名称定义。
例如,假设在Python中有:def a(a_arg): c(a_arg)
def b(b_arg): a()
def c(a_arg,b_arg): b(b_arg)
a(1)
它将在运行时以TypeError: c() takes exactly 2 arguments (1 given)正确地失败,其他错误是编译时错误。(在C语言中,这将编译然后神秘地失败…)
在Perl中,由于子例程名称通常在运行时解析,因此可以按任意顺序使用Perl定义和代码:#!/usr/bin/env perl
a();
b();
c();
sub a{ c(); }
sub b{ a(); }
sub c{ return; }
在C语言中,使用一个未被原型化且不应被忽略的函数是一个错误或警告(依赖于实现)。
你可以这样做:void a(void) { c(); } /* implicitly assumed to be int c(...) unless prototyped */
void b(void) { a(); }
void c(void) { return; }
int main(void) {
a();
return EXIT_SUCCESS;
}
我的假设和困惑是:如果Python直到运行时才解析子例程名称,那么为什么源代码编译阶段会因为尚未定义的子例程名称的前向声明而失败?是否在某个地方(不是通过观察其他代码)记录了不能在子例程定义之上的源文件中包含代码?
Python似乎有dynamic name resolution元素(在源文件下面的定义之前,在a()中使用c())和静态名称解析元素(如果放在源文件中的定义之上,Python无法运行对a()的调用)
是否有一个Python版本的THIS DOCUMENT覆盖了Perl可执行文件的生命周期,以及如何在源文件解释和运行时之间解析名称?
Python脚本的定义顺序中是否有明确的描述,说明函数可以有其他子例程名称的前向定义,但主代码不能?
编辑和总结
经过一些精力充沛的评论和对我的研究,我得出结论,我的问题实际上更多的是关于如何解析名称,以及如何在Python中定义名称空间、作用域和模块。"a callable must be defined before it is called in the current namespace."
and this link on scopes and names"When a name is used in a code block, it is resolved using the nearest enclosing scope."
and this link to the execution life of a Python script.
从Python文档中:"A scope defines the visibility of a name within a block." From the Python Execution model
"A module can contain executable statements as well as function definitions." in more about modules
"In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function enters the function name in the module’s global symbol table." in the footnote thereto.
还有我自己的意识(啊!)即:Python将每个Python源文件视为一个“模块”:“模块是包含Python定义和语句的文件。”
与Perl(我对Perl有更多的经验)不同,Python在读取模块时执行模块。因此,引用尚未在同一模块中定义的函数的立即可执行语句失败。