Python 编码练习:返回 None 和返回相同数据类型的空值?

8 投票
6 回答
3307 浏览
提问于 2025-04-17 14:03

函数返回值和默认值应该使用相同的数据类型吗?还是可以用None?哪种写法更好呢?为什么?

比如,下面是一些Python的伪代码:

/1

def my_position():   # returns a positive integer if found
    if(object is present):
          position = get_position()
          return position # eg 2,3,4,6
    else: 
          return None     # or return -1 or 0 ??

/2

def get_database_rows():    
    do query to whatever database
    if(rows are found):
       return [list of rows]
    else:
       return None  # or return empty list []  ?

/3

the_dictionary = {'a' : 'john','b':'mike','c': 'robert' }  # values are names i.e. non empty string
my_new_var = the_dictionary.get('z', None)  # or the_dictionary.get('z','')  ?

6 个回答

1

还有一个问题中没有提到的选项:抛出异常。在Python中,这种做法似乎挺流行的,有时候遵循你所用语言的常见做法比寻找一个抽象的“最佳”解决方案要好。

关于你的例子:

  1. 我会考虑用 -1,因为这和 “”.find 的做法一致,或者抛出一个 ValueError,因为这就是 [].index 的做法(我并不是说第一个选项是最好的)。我从来不使用从1开始的索引,所以 0 是一个有效的结果,不能用来表示“空”。

  2. 我更倾向于返回一个空列表,因为调用者不一定会把“空”当作一个特殊情况。如果我想统计多个查询的所有行,我不想特别处理 None。如果有一种逻辑上不同的情况,导致行列表“无法生成”(与“没有匹配的行”不同),我会考虑在这种情况下使用 None 或抛出异常。

  3. 一个例子的含义不太清楚,尤其是考虑到 None 是一个有效的字典键。但如果我“必须”在通常期望字符串的地方使用某个特殊值,我会更倾向于使用 None(如果你更喜欢空字符串,重要的是要确保你绝对不需要一个“有效的空字符串”,它只代表它自己,没有其他特殊含义)。

1

一般来说,使用异常处理是比较好的选择,但如果你不想用,那就得看你具体想要什么了。

比如,当你在一个列表中查找一个不存在的项目的索引时,返回 None 和返回 -1 其实差不多,因为这个问题本身就没有好的答案。在调用这个函数后,我必须先检查它是否能给出结果,然后才能继续处理这个结果。

但是,当你想要获取列表中所有奇数的列表时,应该返回 [] 而不是 None,因为 [] 是一个完全有效的答案。我可能想知道原始列表中有多少个奇数,如果没有奇数,那答案就是0,所以像这样

len(odd_numbers(lst))

总是能正常工作。在这种情况下返回 None 会很麻烦,也容易出错,因为我还得做

0 if odd_numbers(lst) is None else len(odd_numvers(lst))
9
  1. 如果找不到某个项目,就抛出一个IndexError错误。这是Python的list的做法。(或者在进行二分查找等操作时,可以返回这个项目应该在的位置索引。)

  2. 想想你的函数逻辑上是做什么的:如果它返回的是数据库中所有满足某个条件的项目的列表,而没有这样的项目,那么返回一个空列表是合理的,因为这样可以让所有常用的列表操作(比如lenin)正常工作,而不需要额外的检查。

    但是,如果缺少这些项目意味着数据不一致,那么就应该抛出一个异常。

  3. 我之前的说法特别适用于这种情况:这取决于你打算怎么处理你得到的值。普通的dict在找不到键时会抛出KeyError错误。你用一个值来替代这个异常,所以你应该知道在你的程序上下文中哪个值是合适的。如果没有合适的值,那就让异常抛出来吧。

不过,返回None通常是个坏主意,因为这可能会掩盖错误。None是Python中的默认返回值,所以一个返回None的函数可能只是因为作者忘记写return语句:

def food(what):
    if what == HAM:
        return "HAM!"
    if what == SPAM:
        return " ".join(["SPAM" for i in range(10)])
    # should raise an exception here

lunch = food(EGGS)    # now lunch is None, but what does that mean?

撰写回答