假设我们有一个检测 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.search
returnNone
来指示某种形式的否定或失败,在这种情况下意味着未找到任何内容。
虽然,在您的特定情况下,否定可以完美地用空列表表示[]
由于它是虚假的,所以返回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所描述的那样,主要是基于意见的),你可以决定你想要的任何东西,没有人会在乎(当你不公开展示它时)你的代码有多灾难性,如果它有效,一切都没关系,如果它不起作用,这一切都不好。