假设我们有一个检测3的倍数的函数。
t1 = (1, 2, 5)
t2 = (3, 6, 9)
def find3(t):
return [x for x in t if not x % 3] or None
我最初的倾向是,如果传入None
,则返回t1
;如果传入[3, 6, 9]
,则返回t2
,如果在任何专业编程环境中都无法使用,
但是,我已经看到很多人说函数应该总是返回相同的类型。这意味着返回[]
而不是None
。
[]
不仅占用更多内存,而且似乎也不太清楚。如果我在数据集上调用find3()
,并且没有倍数,我宁愿看到单词None
而不是空列表,因为它更像现实生活中的语言。
是的,我知道如果在不同的位置使用find3()
的结果可能会导致问题,但是问题的消失只需进行简单的if find3()
检查即可。那么为什么/在所有情况下最好返回[]
?
答案 0 :(得分:2)
赋予某种搜索功能...
找不到单个元素应返回None
;
如果找不到任何预期会出现的元素,则应返回[]
。
某些内置方法,例如re.search
返回None
表示某种形式的否定或失败,在这种情况下,表示未找到。
尽管在您的特定情况下,由于否定falsy可以完美地由空列表[]
表示,所以返回None
并没有好处。
等效于re.search
的列表re.findall
就是这样做的。如果没有匹配项,它将返回[]
。
甚至有实际的原因不返回None
。考虑这段代码...
for x in find3([1, 2, 4]):
...
这将引发一个TypeError
,这是违反直觉的,您必须通过撤消该函数的操作来对其进行修复。
for x in find3([1, 2, 4]) or []:
...
这表明返回None
比这里的事情更痛苦。
答案 1 :(得分:1)
与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所描述的那样,主要是基于意见的),您可以决定所需的内容,没有人会在意(当您不公开展示时)代码的灾难性,如果可以,那么就可以,如果不能,就可以。