Python:为啥模块中不允许“return”

Posted

技术标签:

【中文标题】Python:为啥模块中不允许“return”【英文标题】:Python: why is `return` not allowed in a modulePython:为什么模块中不允许“return” 【发布时间】:2012-08-31 23:09:58 【问题描述】:

如果你查看从模块编译的 Python 字节码,你会看到最后:

10 LOAD_CONST               0 (None)
13 RETURN_VALUE        

return 在模块的根级别完全有效。但是,如果您尝试在源代码中使用它,您会得到:

SyntaxError: 'return' outside function

为什么?


这当然是一个语言设计决定。但为什么被拿走了? return 在模块中通常非常有用。例如。我有时想在模块的开头写这段代码:

import sys
if sys.platform != "linux2":
    print "your platform is not yet supported"
    # define some stubs
    def foo(): pass
    def bar(): pass
    return

而且我不想在那里引发异常(因为这会导致模块无法加载,而我不想要)。


实际上,我一起编写了一些代码,这些代码可以即时操作 Python 字节码并执行返回(或者在我的情况下跳转到完成返回的末尾)。这行得通。它只是 CPython 的唯一原因是因为没有标准的方法来操作代码对象。

Here 是代码。


对于可能的答案:我更喜欢真实的证据,来自 Guido van Rossum 左右的一些过去的陈述,而不是任何随机讨论。我自己当然可以同时兼顾优点(如前所述)和缺点,但我并没有真正看到反对它的主要原因。

【问题讨论】:

你为什么不直接抛出一个异常呢?这将停止执行并返回有关为什么由调用者来监听异常的信息 @JoranBeasley:它不会加载模块。我说的是我仍然想加载模块的情况。 然后有一个单独的模块,用户可以导入......如果它不支持它不应该被支持......在__init__.py你可以做try:import no_linux2; except:import alt_implementation as no_linux2 如果模块的一部分可用而另一部分不可用,那么可以说,它们应该被拆分为处理系统相关内容的子模块,并导入到主模块的命名空间中。 (例如if sys.platform == 'linux2': import _linux_dependent as submod; ...)。这样做的好处是可以将系统相关的代码分开。 这不是一个原因,但这个 when 可能会帮助某人找到答案。它于 1990 年首次出现在 Python/compile.c 中,提交消息为 '"Compiling" version' hg.python.org/cpython/annotate/a6934380c6e7/Python/… 【参考方案1】:

我猜这是 python 开发人员的决定,因为它强制模块的 用户 处理他们的系统不受支持的事实(而不是获得模块的开发人员猜测应该发生什么)。想象一下,当他们在 Windows 机器上运行代码并且突然module.foo() 无法按预期工作时,他们会感到惊讶。 (您的警告print 语句可能会完全隐藏在可能被倾倒到标准输出的各种其他垃圾中)。

我认为处理此问题的最惯用方法是提出ImportErrorNotImplementedError。然后,用户可以决定他们是否可以在没有这个模块的情况下继续工作(通过捕获异常),或者他们的程序是否应该在那里崩溃并烧毁。

【讨论】:

我想不出一个合理的理由为什么要从模块中调用返回... 这对于 Python 来说是非常不寻常的,它通常不会强制太多(恰恰相反)。 @Joran Beasley 我共同开发的一些open-source Python frameworks 将从模块内调用return 的能力中受益匪浅。您个人无法设想一个有效的用例并不暗示不存在有效的用例。 @mgilson 仅仅为了规避语言缺陷而要求if-elif-else 构造既可怕又反Pythonic。如果运气好的话,最终的 Python 4 将纠正这个和其他任意的语法疏忽(例如,将 lambda 函数限制为纯粹的表达式的可怕之处)。 @CecilCurry -- 我认为将lambda 限制在简单的表达式中是一个不错的决定。我已经阅读了太多的 javascript,其中一个内联函数和下一个内联函数之间的界限变得难以辨别:-)。此外,正如我在答案中所说,似乎引发异常是一个比仅仅默默工作更好的决定,但后来在一个不相关的点上死去,因为你期望的东西没有。【参考方案2】:

这不是“为什么”(我怀疑答案只是“return 属于一个函数,没有令人信服的理由将它放在***模块代码中”)。但这是一个您可能不知道的整洁的解决方法。您的代码可以按如下方式重构,而不会增加太多复杂性:

import sys

def main():
    global foo, bar
    if sys.platform != "linux2":
        print "your platform is not yet supported"
        # define some stubs
        def foo(): pass
        def bar(): pass
        return

main()

【讨论】:

以上是关于Python:为啥模块中不允许“return”的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Python 的 `lambda` 表达式中不允许赋值?

Python中不允许使用空格进行正则表达式操作

Python正则表达式—re模块接口

python re模块

python re模块

为啥 WCF 中不允许方法重载?