486

考虑三个函数:

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

他们似乎都返回无。这些函数的返回值的行为方式有什么不同吗?有什么理由更喜欢一个而不是另一个?

4

5 回答 5

651

在实际行为上,没有区别。他们都回来None了,就是这样。然而,所有这些都有时间和地点。以下说明基本上是应该如何使用不同的方法(或者至少是我被教导应该如何使用它们),但它们不是绝对的规则,所以如果你觉得有必要可以将它们混合起来。

使用return None

这表明该函数确实是要返回一个值以供以后使用,在这种情况下它返回None. None然后可以在其他地方使用此值。return None如果函数没有其他可能的返回值,则永远不会使用。

在下面的示例中,如果给定的是人类,我们将返回person's 。如果它不是人类,我们会返回,因为它没有 a (假设它不是动物或其他东西)。motherpersonNonepersonmother

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

使用return

break这与在循环中使用的原因相同。返回值无关紧要,您只想退出整个函数。它在某些地方非常有用,即使您并不经常需要它。

我们有 15 个prisoners,我们知道其中一个有一把刀。prisoner我们一个一个地循环检查他们是否有刀。如果我们用刀打人,我们可以退出函数,因为我们知道只有一把刀,没有理由检查其余部分prisoners。如果我们没有找到prisoner带刀的人,我们会发出警报。这可以通过许多不同的方式完成,并且 usingreturn可能甚至不是最好的方式,但这只是展示如何return用于退出函数的示例。

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

注意:你不应该这样做var = find_prisoner_with_knife(),因为返回值并不意味着被捕获。

return完全不使用

这也将返回None,但该值并不意味着被使用或捕获。它只是意味着函数成功结束。它与 C++ 或 Java 等语言return中的函数基本相同。void

在下面的例子中,我们设置了人的母亲的名字,然后函数在成功完成后退出。

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

注意:你不应该这样做var = set_mother(my_person, my_mother),因为返回值并不意味着被捕获。

于 2013-03-08T18:19:21.737 回答
45

是的,它们都是一样的。

我们可以查看解释过的机器代码,以确认它们都在做完全相同的事情。

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      
于 2013-03-08T18:23:10.773 回答
21

它们每个都返回相同的单例None——没有功能差异。

我认为放弃该return语句是合理的习惯用法,除非您需要它提前退出函数(在这种情况下,barereturn更常见),或者返回除None. return None当它在一个函数中具有另一个返回除None. 显式写出return None是对读者的视觉提示,即有另一个分支返回更有趣的内容(调用代码可能需要处理这两种类型的返回值)。

通常在 Python 中,返回None的函数与 C 中的函数一样使用void——它们的目的通常是对输入参数进行操作除非您使用全局数据(颤抖))。返回None通常会更明确地表明参数已发生变化。这更清楚地说明了为什么return从“语言约定”的角度省略该声明是有意义的。

也就是说,如果您正在使用已经围绕这些东西预先设定约定的代码库,我肯定会效仿以帮助代码库保持统一......

于 2013-03-08T18:13:33.033 回答
11

正如其他人回答的那样,结果完全相同,None在所有情况下都返回。

区别在于风格,但请注意PEP8要求使用一致:

在返回语句中保持一致。函数中的所有 return 语句都应该返回一个表达式,或者它们都不应该返回。如果任何 return 语句返回一个表达式,则任何没有返回值的 return 语句都应将其显式声明为 return None,并且显式 return 语句应出现在函数的末尾(如果可访问)。

是的:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

不:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


基本上,如果你曾经None在函数中返回非值,这意味着返回值是有意义的并且意味着被调用者捕获。因此,当您返回时None,它也必须是明确的,None在这种情况下要传达的意思是,它是可能的返回值之一。

如果您根本不需要 return,那么您的函数基本上是作为过程而不是函数工作的,所以不要包含该return语句。

如果您正在编写一个类似过程的函数并且有机会提前返回(即您已经在该点完成并且不需要执行该函数的剩余部分),您可以使用 empty an returns 向读者发出信号这只是执行的早期完成,None隐式返回的值没有任何意义,也不意味着被捕获(类似过程的函数总是返回None)。

于 2019-12-04T23:36:46.743 回答
4

就功能而言,它们都是相同的,它们之间的区别在于代码的可读性和风格(这是需要考虑的重要因素)

于 2018-10-31T20:13:17.557 回答