函数返回不同的类型是一种不好的做法吗?



假设我们有一个检测 3 倍数的函数:

t1 = (1, 2, 5)
t2 = (3, 6, 9)
def find3(t):
return [x for x in t if not x % 3] or None

我最初的倾向是,没有在任何专业的编程环境中工作过,如果传入t1,我就会返回None,如果传入t2,则返回[3, 6, 9]

但是,我看到很多人说函数应该始终返回相同的类型。这意味着返回[]而不是None

[]不仅占用大量内存,而且似乎也不太清楚。如果我在数据集上调用find3(),并且没有倍数,我宁愿看到单词None而不是空列表,因为它更像现实生活中的语言。

是的,我知道如果find3()的结果在不同的位置使用,这可能会导致问题,但是问题消失所需要的只是一个简单的if find3()检查。那么,为什么/在所有情况下都最好返回[]呢?

经验法则

给定某种搜索功能...

找不到单个元素应返回None;

在预期许多元素时未能找到任何元素应返回[]

解释

一些内置方法(如re.searchreturnNone来指示某种形式的否定或失败,在这种情况下意味着未找到任何内容

虽然,在您的特定情况下,否定可以完美地用空列表表示[]由于它是虚假的,所以返回None没有好处。

列表等价于re.search,即re.findall,正是这样做的。当没有匹配项时,它会返回[]

甚至还有一个实际的理由不返回None.考虑此代码...

for x in find3([1, 2, 4]):
...

这将引发一个违反直觉TypeError,您必须通过撤消函数所做的操作来修复它。

for x in find3([1, 2, 4]) or []:
...

这表明,回归None比这里的任何事情都更痛苦。

我个人更喜欢空列表而不是None,好吧,我不能这么说,这取决于问题是什么。

为什么我应该有一个[](空列表)?

通常,当您在此之后需要执行一些操作时,假设我们要append一个额外的值。

None

def find3(t):
return [x for x in t if not x % 3] or None
l = find3(t1)
l.append(1)
print(l)

输出:

AttributeError: 'NoneType' object has no attribute 'append'

[]

def find3(t):
return [x for x in t if not x % 3]
l = find3(t1)
l.append(1)
print(l)

输出:

[1]

如您所见,None会给您带来错误。

而且,您可以拥有更干净的代码,并获得[]的输出。

我为什么要有None

好吧,通常当你用一个简单的函数完成代码时(如你向我们展示的那样),让代码用户更清楚地看到(我的意思是用户是从未编码过的人)。

两种方法都可以执行相同的语句并传递:

def find3(t):
return [x for x in t if not x % 3] or None
l = find3(t1)
if l:
print('Success')

和:

def find3(t):
return [x for x in t if not x % 3]
l = find3(t1)
if l:
print('Success')

另外,要append这一点,您可以执行以下操作:

def find3(t):
return [x for x in t if not x % 3] or None
l = find3(t1) or []
l.append(1)
print(l)

输出:

[]

or很神奇...

总结:

最后,这都是你的决定(正如SO所描述的那样,主要是基于意见的),你可以决定你想要的任何东西,没有人会在乎(当你不公开展示它时)你的代码有多灾难性,如果它有效,一切都没关系,如果它不起作用,这一切都不好。

最新更新