如何在Python

时间:2017-07-15 04:04:13

标签: python

函数multiply_by_ten采用数字参数,将其乘以10并返回结果。 在此函数执行乘法运算之前,它会检查argument是否为数字。如果argument不是数字,则函数会打印出消息,通知参数不是数字并返回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')

6 个答案:

答案 0 :(得分:22)

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

  1. 它做了两件非常不同的事情:要么做一些数学并返回一个有用的答案,要么打印一条消息。这已经引发了一些危险信号。

  2. 它会向stdout输出错误。实用程序代码应尽可能避免打印,但永远不会stdout投诉。这属于应用程序,而不是虚假错误。

    如果效用函数需要投诉并且没有其他方法可以执行此操作,请使用stderr作为最后的手段。 (但在Python中,你有例外和警告,所以肯定有另一种方法可以做到这一点。)当然,打印调试很好 - 只需确保在完成后删除它。 :)

  3. 如果出现问题,来电者不知道是什么。它得到了None,但这并没有真正解释问题;解释归于一个对此无能为力的人。

    编写正确使用此函数的代码也很困难,因为您可能会得到一个的数字,可能会得到None - 并且因为您只能得到None输入是假的,人们往往不会过多地考虑失败案例,你最终可能会编写代码来假设一个数字回来。

    有时候返回不同类型的值会很有用,但返回一个可以是有效值的值一个错误指示符总是一个坏主意。它正确处理起来比较困难, 正确处理它的可能性更小,而且正是异常要解决的问题。

  4. 首先没有理由成为一个功能!错误检查是float()已经提供的重复工作,并且乘以10不是一个需要将其考虑在内的常见操作。实际上,这会使调用代码更长

  5. 所以我会放弃这个函数并写下来:

    result = float('abc') * 10
    

    奖励:任何Python程序员都会识别float,知道它可能会引发ValueError,并且知道在必要时添加try / except

    我知道这可能是书籍或家庭作业中的一个人为例子,但这就是为什么考虑具有琐碎的例子的架构并不真正有效 - 如果你真的认真对待它,整个例子往往会消失。 :)

答案 1 :(得分:14)

如果作者认为函数应该只返回一种类型(None实际上不是返回值,则在大多数情况下缺少一种),在这种情况下,正确的答案是抛出异常。 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 ++中,一种静态类型语言,可能存在任意,可选,并集和变体的千种不同实现,所有这些实现都旨在将多个类型保存在同一容器中。即使在静态类型语言中,多态也很有用。如果使用sparing,则多态性是语言的一个有用特性。

答案 2 :(得分:9)

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

正如@AGN Gazer指出的那样,通过捕捉错误演员的异常,你会更快,避免你做一个简单的乘法函数:

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

答案 3 :(得分:5)

如果您总是期待某个号码会引发exception,则表示存在问题。

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

最重要的是代码一致性 - 您在代码的其他位置做了什么?

答案 4 :(得分:1)

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

在这种情况下,因为您返回的是数值,而不使用None或表示发生问题的字符串,您将被限制为尝试返回一些数字以指示发生了问题:某些函数返回-1之类的数字作为出现问题的信号。但是,如果输入为-0.1,则在这种情况下不起作用。

正如你所说,如果你真的想要只返回一种类型的值(总是整数或总是浮动),那么除了事先检查之外我没有看到很多选项。

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

答案 5 :(得分:0)

这太傻了。函数始终只返回一种类型。如果该函数可以返回intNone,那么它就是和类型,特别是Optional[int]