我有一个非常简单的例子:
#!/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()
我有 3 个名为a()
, b()
and c()
按字母顺序在 Python 源文件中定义。每个函数定义的主体都是对其他函数之一的调用。从我的评论中您可以看到,我必须对这些函数中的第一个函数进行初始调用(位于其定义下方(在文本文件中)),但您不一定需要在调用它的另一个函数上方定义函数。
当然,将第一个可执行代码放在所有函数定义下面(在 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有以下元素动态名称解析 http://en.wikipedia.org/wiki/Name_resolution#Static_versus_dynamic(指某东西的用途c()
in a()
在下面的源文件中定义之前)和静态名称解析的元素(Python 无法运行对a()
如果放在源文件中其定义之上。)
有Python版本的吗这个文件 http://oreilly.com/catalog/pperl3/chapter/ch18.html#AUTOID-22212涵盖 Perl 可执行文件的生命周期以及如何在源文件解释和运行时之间解析名称?
Python 脚本的定义顺序中是否有明确的描述,指出函数可以具有其他子例程名称的前向定义,但主代码不能?
编辑与结论
经过一些激烈的评论和我的一些研究后,我得出的结论是,我的问题实际上更多是关于如何解析名称,以及如何在 Python 中定义名称空间、作用域和模块。
From 胡萝卜顶 https://stackoverflow.com/questions/4937532/python-name-error-order-of-function-defs/4962566#4962566:
“在当前命名空间中调用可调用对象之前,必须先定义该可调用对象。”
和这个链接 http://docs.python.org/tutorial/classes.html关于范围和名称
From S.Lott https://stackoverflow.com/questions/4937532/python-name-error-order-of-function-defs/4962566#4962566:
“当在代码块中使用名称时,将使用最近的封闭范围来解析它。”
和这个链接 http://docs.python.org/reference/executionmodel.htmlPython 脚本的执行生命周期。
来自Python文档:
“范围定义了块内名称的可见性。”来自Python执行模型 http://docs.python.org/reference/executionmodel.html#index-918
“模块可以包含可执行语句以及函数定义。”在有关模块的更多信息 http://docs.python.org/tutorial/modules.html#more-on-modules
“事实上,函数定义也是‘执行’的‘语句’;模块级函数的执行会将函数名称输入到模块的全局符号表中。”在其脚注中。
我自己的认识(呃!):
每个 Python 源文件都被 Python 视为一个“模块”:“模块是包含 Python 定义和语句的文件。”
与 Perl(我对此有更多经验)不同,Python 在读取模块时执行它们。因此,引用同一模块中尚未定义的函数的立即可执行语句会失败。