返回,返回 None,根本没有返回?

return, return None, and no return at all?

提问人:Clay Wardell 提问时间:3/9/2013 最后编辑:Karl KnechtelClay Wardell 更新时间:3/27/2023 访问量:519067

问:

请考虑以下三个功能:

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

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

他们似乎都回来了。这些函数的返回值的行为方式之间是否存在任何差异?有什么理由偏爱其中一种吗?None


Смотритетакже: 是否可以不从 python 中的函数返回任何内容?

python null 返回

评论

70赞 3/9/2013
请注意,存在风格差异。 对我来说,这意味着该函数有时具有非返回值,但在 的位置,没有这样的返回值。写“不”对我来说意味着永远不会有一个有趣的返回值,有点像“过程”而不是“函数”。 暗示根据上一点,从“程序”早期存在。return NoneNonereturn Nonereturnreturn

答:

28赞 mgilson 3/9/2013 #1

它们各自返回相同的单例 -- 没有功能差异。None

我认为省略语句是合理的惯用语,除非您需要它提前脱离函数(在这种情况下,裸露更常见),或者返回 .它也是有道理的,当它位于具有另一个路径的函数中时,编写似乎是惯用的。显式写出是向读者发出的视觉提示,即还有另一个分支返回更有趣的东西(并且调用代码可能需要处理这两种类型的返回值)。returnreturnNonereturn NoneNonereturn None

通常在 Python 中,返回的函数就像 C 中的函数一样使用——它们的目的通常是对输入参数进行操作(除非你使用的是全局数据(不寒而栗))。返回通常会更明确地表明参数已发生突变。这就更清楚地说明了为什么从“语言约定”的角度省略该语句是有意义的。NonevoidNonereturn

也就是说,如果你在一个已经围绕这些事情预先设定了约定的代码库中工作,我肯定会效仿来帮助代码库保持一致......

评论

1赞 3/9/2013
或者更一般地说,每当函数在不命中语句的情况下结束时,它都会返回 。returnNone
1赞 mgilson 1/11/2018
@ZAB——我认为这是不可能的。在 python 中,我可以用任何东西来修补任何东西(这是设计使然,如果谨慎使用,这是一个很棒的功能)。具体来说,我可以用一个没有返回值的函数来修补一个函数。所有“非表达式”检查都发生在解析时,但由于猴子修补,这要到运行时才能发生。哎呀,完全不同。就我个人而言,我认为当前的行为是相当合理的(并且与其他高级语言一致),但我不是你需要说服的人:-)。
1赞 mgilson 1/13/2018
@ZAB -- 两者都采用与 python 相同的方法。我敢肯定,有一些高级语言的例子在表达式中说“void”,但我目前想不出任何一个(也许如果你考虑一种高级语言)......在一个假设的世界中,猴子修补函数(这对于测试中的模拟等很有用)将如何工作,其中 python 得到了一个关键字,使该函数不返回任何内容?(另外,正如我之前所说,你不需要说服我这是一个糟糕的设计。即使你是对的,我也无能为力)RubyJavascriptJavavoid
1赞 ZAB 1/16/2018
@GregSchmit没有。将 None 分配给变量与使其保持未初始化状态不同。你可以从变量中读取 None,你可以检查它并在 if 条件中使用它,但你不能读取和使用未初始化的变量,你会得到一个异常。函数返回值也应该如此。
1赞 Greg Schmit 2/4/2018
此外,正在初始化,因此抛出未初始化的错误将毫无意义。生活中的全部工作就是与任何事物(任何有意义的值)相反,所以当一个函数不返回任何东西时,这与返回是一样的。a = myfunc()aNoneNone
754赞 user2032433 3/9/2013 #2

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

return None

这说明该函数确实是为了返回一个值供以后使用,在这种情况下,它返回 .然后,可以在其他位置使用此值。 如果函数中没有其他可能的返回值,则从不使用。NoneNonereturn None

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

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

return

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

我们有 15 个,我们知道其中一个有一把刀。我们一一循环检查他们是否有刀。如果我们用刀打人,我们可以退出该功能,因为我们知道只有一把刀,没有理由检查其余的.如果我们没有找到带刀的人,我们会发出警报。这可以通过许多不同的方式完成,使用可能不是最好的方法,但这只是一个示例,展示了如何使用退出函数。prisonersprisonerprisonersprisonerreturnreturn

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

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

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

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

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

评论

16赞 joel 11/16/2018
var = get_mother()如果您要传递给其他接受的函数,则可以 - “从不”有点极端varNone
0赞 winklerrr 12/10/2018
如果不能使用,应该如何接受返回值?恕我直言,这样做是完全可以的。您只需要确保在使用前检查非值。var = get_mother()Noneif var
0赞 Fabiano 12/5/2019
我认为值得一提的是,这不仅仅是一个好的约定,它是 PEP8 所要求的。我发布一个答案来赞美你的答案,并就此引用 PEP8。
0赞 Artur Müller Romanov 7/13/2020
为什么不应该是?return valuescaught
52赞 David Marx 3/9/2013 #3

是的,它们都是一样的。

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

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      

评论

8赞 mgilson 3/9/2013
小心这里... 返回:-Xdis.disNone
0赞 mgilson 3/9/2013
将 dis 的输出作为字符串的唯一方法是将 stdout 重定向到某种 IO 缓冲区(例如 StringIO)。即便如此,像这样直接比较可能不起作用,因为我相信也会报告一些行号......dis.dis
0赞 David Marx 3/9/2013
无论如何,他们是否使用完全相同的寄存器都无关紧要,所以我更改了我的代码,所以我们现在只是关注机器代码,而不是进行某种愚蠢的字符串比较。谢谢你的大提醒。
0赞 ruohola 9/25/2020
@mgilson 现在也可以使用 dis。字节码.dis()。
5赞 Yehuda Schwartz 11/1/2018 #4

在功能方面,它们都是一样的,它们之间的区别在于代码的可读性和风格(这也是需要考虑的重要因素)

27赞 Fabiano 12/5/2019 #5

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

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

在 return 语句中保持一致。要么将所有 return 语句放在 函数应该返回一个表达式,或者它们都不应该返回。如果有的话 return 语句返回一个表达式,任何 return 语句 no value is 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


基本上,如果你在函数中返回非值,这意味着返回值有意义,并且应该被调用者捕获。所以当你返回时,它也必须是明确的,在这种情况下传达有意义,它是可能的返回值之一。NoneNoneNone

如果你根本不需要 return,你的函数基本上是作为一个过程而不是一个函数来工作的,所以不要包含这个语句。return

如果你正在编写一个类似过程的函数,并且有机会提前返回(即你已经完成了,不需要执行函数的其余部分),你可以使用空的 s 来向读者表示它只是执行的早期完成,隐式返回的值没有任何意义,也不应该被捕获(无论如何,类似过程的函数总是返回)。returnNoneNone