如何在Python中处理函数返回值

如何在Python中处理函数返回值,python,Python,函数multiply\u by\u ten接受一个数值参数,将其乘以10并返回结果。 在该函数执行乘法之前,它会检查参数是否为数值。如果参数不是数字,则函数将打印消息,通知该参数不是数字,并返回None 问题。一些开发人员认为,无论在何种情况下,任何给定函数都应该返回相同类型的值。所以,如果我遵循这样的观点,那么这个函数不应该返回None。如何处理这样的情况?在将参数发送到函数之前是否应检查该参数?为什么? def multiply_by_ten(arg): if not str(ar

函数
multiply\u by\u ten
接受一个数值参数,将其乘以10并返回结果。 在该函数执行乘法之前,它会检查
参数
是否为数值。如果
参数
不是数字,则函数将打印消息,通知该参数不是数字,并返回None

问题。一些开发人员认为,无论在何种情况下,任何给定函数都应该返回相同类型的值。所以,如果我遵循这样的观点,那么这个函数不应该返回None。如何处理这样的情况?在将参数发送到函数之前是否应检查该参数?为什么?

 def multiply_by_ten(arg):
    if not str(arg).isdigit():
        print 'arg is not a digit'
        return
    return float(arg) * 10


result = multiply_by_ten('abc')

Python中处理错误的常见做法不是返回与预期值类型不同的值,而是引发异常

正如所指出的,通过捕获错误转换的异常,避免使用函数进行简单的乘法运算,您可以更快地执行操作:

try:
   result = float('abc') * 10
except:
   print('Error: not a valid number')
如果我们继续使用您的旧代码结构,而不是:

def multiply_by_ten(arg):
   if not str(arg).isdigit():
       print 'arg is not a digit'
       return
   return float(arg) * 10
你应该做:

def multiply_by_ten(arg):
   if not str(arg).isdigit():
       raise Exception('NotNumber', 'The argument is not a number')
   # Do some other stuff? Otherwise not really helpful
   return float(arg) * 10
在您的通话中:

try:
   result = multiply_by_ten('abc')
catch Exception as e:
   if e.args[0] == 'NotNumber':
      print('Error: '+e.args[1])
   else:
      raise

如果作者认为函数应该只返回一种类型(没有一种类型实际上不是返回值,在大多数情况下是没有返回值),那么在这种情况下正确的答案是抛出异常。IMO,这里使用EAFP原则的正确逻辑是:

 def multiply_by_ten(arg):
    return float(arg) * 10


try:
    result = multiply_by_ten('abc')
except ValueError:
    pass
我也不建议重复标准库已经为您做的事情,因为您自己的实现通常比已经为您做的更糟糕。例如:

>>> "0.01e-6".isdigit()
False
>>> float("0.01e-6")
1e-8
如果函数已经检查了传递给它的参数的有效性,并在失败时抛出异常,则无需再次检查

最后,我认为函数应该返回单一类型的想法是危险的:异常处理很好,返回无效标志也很好,但Python是一种动态语言,其原因是:它允许设计多态性。合理地使用它


最后,有一点看法。在C++中,静态类型的语言可能存在任意、可选、联合和变体的一千种不同的实现方式,它们的目的是在同一容器中保存多种类型。即使在静态类型语言中,多态性也很有用。如果使用备用,多态性是一种有用的语言功能。

如果您总是期待一个数字,则会引发一个异常,这意味着出现了问题

如果值可能丢失,并且与程序逻辑没有任何冲突,则返回
None


最重要的是代码的一致性——在代码的其他地方你会做什么?

说任何给定函数只应返回一种类型的值的任意决定就是:任意

在这种情况下,由于您返回的是一个数值,而没有使用
None
或表示出现问题的字符串,因此您只能尝试返回一些数字来表示出现了问题:有些函数返回像-1这样的数字作为出现问题的信号。但在这种情况下,如果输入为-0.1,则这将不起作用

如您所说,如果您真的只想返回一种类型的值(总是int或总是float),那么除了预先检查之外,我看不到其他很多选项


选项可能包括按照其他作者的建议使用try/except语句。

我写的这个函数有很多问题

  • 它做两件截然不同的事情:要么做一些数学运算并返回一个有用的答案,要么打印一条消息。这已经引起了一些危险信号

  • 它将错误打印到
    stdout
    。如果可能的话,实用程序代码应该避免打印,但它应该从不
    stdout
    投诉。这属于应用程序,而不是伪错误

    如果实用程序功能需要投诉,并且没有其他方法可以投诉,请使用
    stderr
    作为最后手段。(但在Python中,您有异常和警告,因此肯定有另一种方法可以做到。)当然,打印调试很好-只需确保完成后将其删除即可。:)

  • 如果出了什么问题,打电话的人不知道该怎么办。它返回一个
    None
    ,但这并不能真正解释问题;这个解释适用于一个对此无能为力的人

    编写正确使用此函数的代码也很困难,因为您可能会得到一个数字或
    None
    ——并且因为只有当输入是虚假的时,您才会得到
    None
    ,而且人们往往不会过多地考虑失败案例,所以您很有可能最终编写出假定数字返回的代码

    返回不同类型的值有时很有用,但返回一个可以是有效值或错误指示器的值总是一个坏主意。它更难正确处理,也不太可能正确处理它,而这正是异常要解决的问题

  • 首先,没有理由让它成为一个函数!错误检查是由
    float()
    提供的重复工作,并且乘以10不是一种常见的操作,因此需要将其分解。事实上,这使得调用代码更长

  • 因此,我将删除该函数,并编写以下内容:

    result = float('abc') * 10
    
    好处:任何Python程序员都会识别
    float
    ,知道它可能会引发
    ValueError
    ,并且知道在必要时添加
    try
    /

    我知道这可能是一本书、家庭作业或其他东西中的一个人工例子,但这就是为什么考虑用琐碎的例子来构建架构并不能真正起作用的原因——如果你真的认真对待它,整个