一个函数只应有一个 return 吗?什么时候应该提前 return,什么时候应该用 else 语句?

2018-04-28 23:36:50 +08:00
 roy2220

一个对编码有所追求的人,想必被些问题困扰过。由于这些问题很晦涩,多种写法都是等价的,很少人会把它摆上台面认真的讨论,下面我来分享一下我的思索。

一个函数只应有一个 return 吗?——即对又错。没有意外情况只应有一个 return,意外情况要提前 return (导致多个 return )。举例:

students = dict(...)

# 正确的写法
def get_studen_age(studen_name): # 需求:若学生不存在返回-1
    student = students.get(studen_name, None)
    if student is None: # 意外情况
        return -1
    student.access_count += 1 # 需求:增加访问计数
    return student.age

# 错误的写法[1]
def get_studen_age(studen_name):
    student = students.get(studen_name, None)
    if student is None: # 意外情况
        return -1 # 错误情况应该尽早返回,代码可读性更佳
    else:
        student.access_count += 1
        return student.age

# 错误的写法[2]
def get_studen_age(studen_name):
    student = students.get(studen_name, None)
    if student is None: # 意外情况
        student_age = -1 
    else:
        student.access_count += 1
        student_age = student.age
    return student_age # 错上加错,只有一个 return,营造没有错误情况的假象

什么时候应该提前 return,什么时候应该用 else 语句?——正如上面的例子所说,意外情况才要提前 return,否则写在 else 语句里。这又引入了另一个问题:怎么定义意外情况?有一个衡量的方法:if 条件... : [THEN] else [ELSE] 如果在普遍情况下[THEN]部分和[ELSE]部分执行的频度一致,说明没有意外情况,否则[THEN]部分和[ELSE]部分两者中执行频度较低的一方可判定为意外情况(通常为错误处理)。举例:

# 正确的写法
def min(a, b):
    if a < b:
        r = a
    else:
        r = b
    # 普遍情况下[r = a]和[r = b]执行的频度(运行的机会)是一致的,这里没有意外情况
    return r

# 错误的写法
def min(a, b):
    if a < b:
        return a # 这里不该应该是意外
    return b
3673 次点击
所在节点    程序员
13 条回复
crb912
2018-04-29 02:00:46 +08:00
任何函数,只有要返回值,都有且仅有一次 return。你虽然前面的代码有多个 return,但处于 if 构建的分支中(有无 else 都一样)。

我探讨几个问题吧。
1.你"#错误的写法[1]"和"#正确的写法",这两个例子有区别吗?
我的看法:
没任何区别,无非多了一个 else。写不写 else 都可以,纯属看个人爱好。反而,理论上,写 else 代码逻辑更清晰点,别人一目了然。方便粗心的程序员阅读你的代码。所以"错误的写法"真的错误吗?不见得,而且我认为它是一种不错的方式。

2."错误的写法[2]"又哪里错了吗? 当 if 成立,它立马 return 了错误值-1,难道它没有满足你说的"提前 return"?早知道,此时 else 的语句是不会执行的。
autoxbc
2018-04-29 09:21:00 +08:00
卫语句的讨论是周经了,估计又要火一帖
roy2220
2018-04-29 10:34:23 +08:00
@crb912 感谢讨论。每个人对代码可读性的理解不一样,其实这个问题没有的唯一正确的答案。上面所说的"正确"、"错误"并非指功能实现上,而且是风格上的。你指出的第 1 点主要是例子 1 的意外情况只有一个不太明显,如果例子 1 的意外情况很多,都用 if else 的写法,处理正常情况的逻辑会被嵌套得很深,不能一眼找出正常逻辑的部分
roy2220
2018-04-29 10:41:42 +08:00
@crb912 关于你的第二点,其实是我的描述不对,我所定义的"尽早返回"应该是直截了断,不应该留下 else 部分
crb912
2018-04-29 11:16:48 +08:00
关于要不要 else,我看过书里这么讲的:
The else isn't needed,but it does help the casual reader understand the intent. —— 《 C++ Primer Plus 》第六版 p308.
roy2220
2018-04-29 11:32:28 +08:00
@crb912 如果真的有一些简单武断的原则,只要竭力去遵守就能写出好代码,那满世界都是优秀程序员了,因为这太简单就能做到了。但现实并不是那么简单,动态地权衡和取舍才能做出好决定,不要盲目地相信各种原则(例如 DRY ?),它们通常都隐含着应用情景,无视应用情景妄想一招鲜,不是懒就是傻
woscaizi
2018-04-30 10:26:51 +08:00
实际代码中多个 return 没什么不妥吧,把逻辑处理好就可以。拙见。
roy2220
2018-04-30 11:10:14 +08:00
@woscaizi 光把逻辑写对还不够,可读性很重要,本主题的核心就是 return 与代码的可读性
woscaizi
2018-04-30 13:13:42 +08:00
@roy2220 我觉得多个 return 与多个 else 可读性一致。
roy2220
2018-04-30 13:33:36 +08:00
@woscaizi 所以说这本身就是个很主观的问题。本主题的定位人群是认为 return 和 else 可读性不一致、想在两者寻找一个平衡的人,你大可无视本主题,它和你没什么关系
woscaizi
2018-04-30 13:58:19 +08:00
@roy2220 #10 你太紧绷了,我只是说出我的观点,而你你只是想找认同你的人。
roy2220
2018-04-30 14:46:12 +08:00
@woscaizi 然而。。。并不是,其实我一开始我就不想回复你(因为觉得没有讨论的共识),但是又怕让你觉得我不太礼貌,只能硬着头皮回复(同时委婉表明我的态度),结果越来越尴尬。。。还是就此打住吧
woscaizi
2018-04-30 15:50:04 +08:00
@roy2220 怪我话多。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/450806

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX