Python过程返回值

19 投票
6 回答
39620 浏览
提问于 2025-04-15 15:03

在Python中,可以创建一个没有明确返回值的过程,也就是说:

def test(val):
    if 0 == val:
        return 8

而且,可以把这个函数的结果赋值给一个变量:

>>> a = test(7)
>>> print `a`
'None'

这到底是为什么呢?背后有什么样的语言逻辑让人困惑?为什么不直接抛出编译错误呢?

编辑:是的,我知道它是这样工作的。谢谢。我的问题是为什么?这似乎很容易在代码中引入一些微妙的错误。而且,正如下面的e-satis提到的,这似乎与“明确优于隐含”的Python哲学相悖。

那么,这到底是怎么回事?这是设计上的疏忽,还是简化的假设,或者是经过深思熟虑的决定?

编辑:大家是否同意用这种方式表达意图要好得多:

def test(val):
    if 0 == val:
        return 8
    else:
        return None

如果是这样,为什么Python会更倾向于前一种风格,而不是抛出编译时异常呢?

编辑:S.Lott明确指出(其他人也提到过,他的说法对我来说最清晰),这种行为是因为Python是一种动态语言,因此无法在编译时检查系统的运行时行为。

由于过程(不返回值的函数)和函数(返回值的函数)之间没有区别,所以在编译时没有什么可以强制执行的。这意味着在运行时,我们可能会遇到灾难性的失败(抛出异常),或者默默失败,假设程序员知道自己在做什么,并理解默认行为。

Python的做法是后者,而C风格的做法是前者。
这似乎是一个合理的理由。

S.Lott的清晰解释埋在了接受答案的评论中,所以我觉得在这里总结一下比较好。

我会暂时不接受这个答案,看看S.Lott是否会给出正式的回答。否则,我会把分数给SilentGhost。

6 个回答

8

嘿,从Java的角度来看,你的问题很明显。它应该会报错。

但是如果从Perl的角度来看,这就不那么明显了。你只是把一个变量设置为没有值,这有什么大不了的呢。

这主要是关于类型的。像Java一样,Python是强类型的,但与Java不同的是,它还是动态类型的。大多数动态类型的语言都允许像这样的小把戏。

12

Python 这个语言不会去检查人类的错误行为。它的设计理念是相信程序员都是成年人,知道自己在做什么。

原因有:

  • Python 是一种自我文档化的语言,所以你可以很快知道一个函数会返回什么;
  • Python 使用鸭子类型,这样默认返回 None 可以让动态调用函数变得简单很多。

返回 None 比抛出错误更合理。

举个例子:

function_stack = [func1, func2, func3]

for f in function_stack :
    a = f()
    if a is not None :
        # do something

不管 f 是一个函数还是一个过程,在 Python 中都没有这个区分。你可以调用所有的函数,然后处理它们的输出(如果有的话)。

28

虽然每个函数可能没有明确的返回值,但它们实际上会有一个隐含的返回值,那就是 None,而且 None 也是一个普通的 Python 对象。此外,函数通常会明确地 return None

我想,隐含返回 None 只是为了让使用起来更方便。

附言:我想知道在以下情况下,编译器会怎么处理:

def t():
    if True:
        return 'ham'

再附言: return 语句表示需要返回某些东西,无论是 None42 还是 'spam'。不过,有些函数其实并不返回任何东西,比如 list.sort__init__,所以在每个 __init__ 的最后都要求写 return None 就显得有些多余了。

撰写回答