【问题标题】:Python raise Error proper usePython引发错误正确使用
【发布时间】:2013-01-10 08:51:21
【问题描述】:

说明

我读过很多关于在 python 中检查值类型的意见,大多数人说你不应该检查类型,而是使用 try 和 except。 我想澄清几件事。

问题

当我有这样的方法时:

def set_age(self, age):
    self._age = age

我不能让用户传递除 int 以外的任何类型,因为稍后在代码中可能会导致一些更难调试的错误。 根据 Python 方法,我无法检查类型。 那么我应该如何以正确的方式尝试呢?

def set_age(self, age):
    try:
        age = int(age)
    except TypeError:
        raise TypeError('First parameter must be of int type.')
    self._age = age

或者只是

def set_age(self, age):
    self._age = int(age)

并让 Python 自行引发错误。

我知道这可能是一些愚蠢的问题,我只是想确定一下。

【问题讨论】:

  • “稍后在代码中可能会导致一些更难调试的错误”——然后你必须修复 那个 代码。目前,您尝试在错误的地方解决问题。
  • 它还没有解决,只是找到开始寻找的地方。在我的应用程序中,我有很多后来被打包成二进制格式的参数。当打包函数引发无法打包的错误时,它不会告诉我要打包的数据来自哪里,因为它是一个大数组,附加到代码中其他地方的数组。当我在打包之前发现类型错误异常时,我知道什么值不会打包。当我现在考虑它时,我应该在将其设置为对象之前验证值。但是验证器再次以某种方式进行类型检查,所以我不知道该怎么想
  • 检查某物是否适合使用和类型检查之间存在巨大差异。在某些语言中它们是相同的东西,但在 Python 中它们是完全不同的。请注意,类型检查并非总是不好——它几乎是区分字符串和任意序列的唯一方法。然而,在大多数情况下,它是不必要的,而且弊大于利。

标签: python exception typechecking raise


【解决方案1】:

如果它不是整数,Python 将引发相应的错误,因此无需将您自己的错误置于其顶部。

让我们退后一步,因为这里还有其他问题。 getter 和 setter 真的是 unpythonic - 要么只使用一个属性,要么使用properties

在这种情况下,我认为您仍然在以错误的方式思考。我们不在 Python 中进行类型检查的原因是因为我们不应该关心某个东西是什么类型,只要它在给定的情况下可以工作。把所有东西都变成你认为应该的类型,本质上就是类型检查。

您说这会使调试变得更加困难,但这并不是大多数人真正拥有的经验。鸭子打字旨在让任何可以完成这项工作的东西都能完成这项工作。将所有内容转换为 int 会限制您的程序。问题不在这里,问题在于您的代码传递了一些对您的类没有意义的东西。以我的经验,这实际上是一件非常罕见的事情——你不会倾向于在课堂上随意扔东西,看看有什么效果。

所以,我在这里的建议是您使用属性 - 只需使用 x.age = ... 而不是使用 set_age() 或类似的东西。如果您真的需要int(如,只有整数才有意义),然后使用属性并在设置器中调用int(),如果出现以下情况,则将错误传播给调用者它发生了。

【讨论】:

  • 感谢您的回答。我忘了提到我使用的是 python 2.7,但幸运的是它也支持属性。我使用 setter 和 getter 是因为以后可能需要对值进行一些额外的检查,然后在代码中找到我所有的 x.age = ... 会很痛苦。尽管我不知道这是否真的是一个问题。我的第一语言是 C++,我必须改变我的想法。
  • @RafałŁużyński Properties 解决了这个问题。如果您有一个属性,并且您决定需要它的功能,请创建一个属性。然后,该属性对调用者的行为完全相同,因此接口不会改变。除非你需要否则只使用一个属性。
【解决方案2】:

python 的一个信条是“请求原谅比请求许可更好”。很多时候,你的函数调用所产生的异常足以告诉你的函数的调用者出了什么问题。

话虽如此,在某些情况下,我会抛出一个更具体的异常,即调用者的语义不完全一致。我能想到的一个例子是我正在检查一个 json 响应并且我在字典的一个元素上得到一个“关键错误”。这通常意味着我发出的任何请求都失败了,因此我找不到我需要的数据。反过来,我会根据我的函数(例如“查询失败”)在语义上抛出一些东西。

虽然被调用函数“类型错误”或“io 错误”抛出的异常对我的函数的调用者来说应该是完全有意义的,但我不必费心捕捉和重新抛出异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 2014-03-06
    • 2018-11-15
    • 2018-05-03
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多