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
语句可能会完全隐藏在可能被倾倒到标准输出的各种其他垃圾中)。
我认为处理此问题的最惯用方法是提出ImportError
或NotImplementedError
。然后,用户可以决定他们是否可以在没有这个模块的情况下继续工作(通过捕获异常),或者他们的程序是否应该在那里崩溃并烧毁。
【讨论】:
我想不出一个合理的理由为什么要从模块中调用返回... 这对于 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”的主要内容,如果未能解决你的问题,请参考以下文章