Python:名称解析;函数 def 的顺序

2024-02-17

我有一个非常简单的例子:

#!/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

“事实上,函数定义也是‘执行’的‘语句’;模块级函数的执行会将函数名称输入到模块的全局符号表中。”在其脚注中。

我自己的认识(呃!):

  1. 每个 Python 源文件都被 Python 视为一个“模块”:“模块是包含 Python 定义和语句的文件。”

  2. 与 Perl(我对此有更多经验)不同,Python 在读取模块时执行它们。因此,引用同一模块中尚未定义的函数的立即可执行语句会失败。


定义的顺序很简单:“所有内容都必须在调用之前定义”。差不多就这样了。

edit(在评论中包含答案,并加以说明):

原因类似

def call_a():
    a()

def a():
    pass

call_a()

当你有的时候就可以工作a() in call_a() before a甚至被定义为一个函数,因为Python实际上只是在一个函数上查找符号的值如所须基础。什么时候call_a被评估时,a()调用基本上存储为字节码指令“查找什么”a是并称之为“在时机成熟时,直到您开始实际调用call_a()在底部。

这是反汇编的字节码call_a看起来像(通过dis.dis http://docs.python.org/library/dis.html#dis.dis):

Disassembly of call_a:
  2           0 LOAD_GLOBAL              0 (a)
              3 CALL_FUNCTION            0
              6 POP_TOP
              7 LOAD_CONST               0 (None)
             10 RETURN_VALUE

所以基本上,当你击中call_a,它加载存储为的任何内容a入栈,将其作为函数调用,然后在返回之前将返回值弹出None,这就是任何未显式返回的内容隐式发生的情况(call_a() is None回报True)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python:名称解析;函数 def 的顺序 的相关文章

随机推荐

  • 如何在数据框列表上使用 devtools::use_data?

    我有一系列数据框 我想将它们保存为包中的单独 rda 文件 我可以用devtools use data my df1 my df2 但我没有每个数据帧的命名对象 它们都存储在一个大列表中 我想要做的是为每个列表元素调用 use data 并
  • 如何从我的代码中删除重复项

    我有两个类似的方法 其中一个打印一些东西 其中一个保存一些东西 正如你所看到的 有很多重复的代码 我应该如何重构它并删除这种重复 public static void printSomething List
  • 在玩笑中模拟节点模块中的特定类

    我想嘲笑Socket类来自net节点模块 Docs https nodejs org api net html net class net socket 我有一堂课看起来像这样 import Socket from net class Fo
  • 在浏览器上通过php运行python脚本

    我有一个简单的 python 脚本 阿努巴哈 py usr bin env python coding UTF 8 enable debugging import cgitb import pandas cgitb enable print
  • 将新项目动态添加到 IQueryable 硬编码假存储库

    在使用真正的数据库之前构建应用程序 为了让事情正常工作 我可以首先使用硬编码列表作为假的内存存储库 public class FakeProductsRepository private static IQueryable
  • RecyclerView 项目不填充宽度

    我设计了一个带有地图片段和recyclerView的布局 每个recyclerView项目都是cardview 我已经指定给出xml布局 问题是 RecyclerView 项目不填充屏幕宽度 img here https i stack i
  • Scrapy图片下载如何使用自定义文件名

    For my scrapy http doc scrapy org index html我目前正在使用的项目图片管道 http doc scrapy org topics images html scrapy contrib pipelin
  • 防止小部件填充 Flutter 中扩展的祖先

    我如何保留一个RaisedButton从扩大到填补Expanded包含它 我想创建三列 其宽度与可用空间成比例 但我希望每列中的子项为其自然大小 而不消耗其父项的整个宽度Expanded Widget controls BuildConte
  • 如何将多部分表单数据从jsp发送到Web服务?

    我正在尝试为我的网站创建一个注册页面 当用户将数据提交到signup jsp时 我想使用 application x www form urlencoded 将此数据发送到我的Web服务 我怎样才能在JSP中做到这一点 尝试了以下代码 但这
  • 如何将字符串从函数传递到主函数?

    我尝试寻找解决方案 但未能找到 是否可以返回字符串 我想将一个字符串从下面的函数传递回 main 我想通过listofdeatils string 这是我的代码 include
  • 如何使用 Fetch 发布 x-www-form-urlencoded 请求?

    我有一些参数想要以表单编码的方式 POST 到我的服务器 userName email protected cdn cgi l email protection password Password grant type password 我
  • 如何链接winsock.lib?

    在我的 C 课程中 我使用套接字 我在链接时遇到一些错误 因为在我看来 库 Winsock lib 丢失了 我包括这些 ifdef WIN32 include
  • Pro JavaScript 程序员面试问题(含答案)[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 重定向到登录页面时正确的 HTTP 状态代码是什么?

    当用户未登录并尝试访问需要登录的页面时 重定向到登录页面的正确 HTTP 状态代码是什么 我问是因为没有一个W3C 规定的 3xx 响应代码 http www w3 org Protocols rfc2616 rfc2616 sec10 h
  • 插入表..在链接服务器上执行不起作用

    这有效 返回结果集 exec select col count 1 from test dbo Table1 with nolock at svrA 当我尝试将结果集插入表中时 insert into rowcount sub tablen
  • 如何在 IIS 7 中配置 Http 处理程序?

    这就是我想做的 我创建了一个类库项目 这有一个类实现 IHttpHandler 接口 让我们 将该类命名为 ZipHandler 让我们 假设命名空间是 Zip 我希望每当任何 Http 请求提供 zip 文件 我的 ZipHandler
  • PHP 有类似 ruby​​ gem 的打包器吗?

    我是 PHP 程序员 了解 Rails Ruby 宝石捆绑器 http gembundler com 非常好的安装依赖项的工具 php有类似的东西吗 也许某些php框架有这样的工具 关于gem捆绑器的说明 Bundler 在应用程序的整个生
  • MalformedInputException 与 Files.readAllLines()

    我正在迭代一些文件 准确地说是 5328 个文件 这些文件是平均 XML 文件 最多 60 200 行 它们首先通过简单的方法进行过滤isXml源文件解析路径 Files walk Paths get home me development
  • 如何使用 codeigniter 查询获取每个产品的平均评分?

    我有评级表 其中对用户给出的每个产品进行评级 我正在检索所有评级记录 但同时我想根据每个产品获得平均评级 但我无法获得输出 Query this gt db gt select ratings this gt db gt select se
  • Python:名称解析;函数 def 的顺序

    我有一个非常简单的例子 usr bin env python a 1 NameError name a is not defined b 1 NameError name b is not defined c 1 NameError nam