Which exception should I raise on bad/illegal argument combinations in Python?
我想知道在Python中指示无效参数组合的最佳实践。我遇到过一些情况,你有这样的功能:
1 2 3 4 5 6 7 8 9 10 11
| def import_to_orm(name, save=False, recurse=False):
"""
:param name: Name of some external entity to import.
:param save: Save the ORM object before returning.
:param recurse: Attempt to import associated objects as well. Because you
need the original object to have a key to relate to, save must be
`True` for recurse to be `True`.
:raise BadValueError: If `recurse and not save`.
:return: The ORM object.
"""
pass |
唯一的麻烦是每个包都有自己的,通常略有不同的BadValueError。我知道在Java中存在EDCOX1,1个-很好地理解,每个人都将在Python中创建自己的EDCOX1,0个s,或者有另一个优选的方法吗?
我只会提出valueerror,除非您需要更具体的异常。
1 2 3
| def import_to_orm(name, save=False, recurse=False):
if recurse and not save:
raise ValueError("save must be True if recurse is True") |
实际上,执行class BadValueError(ValueError):pass没有意义——您的自定义类在使用valueerror时是相同的,那么为什么不使用它呢?
- >"那为什么不使用它呢?"特异性。也许我想捕捉一些外层的"myValueError",但不是任何/所有的"valueError"。
- 是的,所以特殊性问题的一部分是在哪里提出了valueerror。如果被调用函数喜欢您的参数,但在内部调用math.sqrt(-1),则调用程序可能会捕获valueerror,因为它的参数不合适。也许你只需检查一下这个案例中的信息…
- 我不确定这个论点是否成立:如果有人调用math.sqrt(-1),这是一个编程错误,无论如何都需要修复。ValueError不打算在正常程序执行中被捕获,或者它将从RuntimeError派生。
- 如果错误在参数个数上,对于参数个数可变的函数…例如,一个函数,其中参数必须是偶数个参数,那么您应该引发一个类型错误,以保持一致。并且不要创建自己的类,除非a)您有一个用例,或者b)您正在导出库以供其他人使用。过早的功能是代码的死亡。
我要从以东王那里继承
1 2
| class IllegalArgumentError(ValueError):
pass |
有时最好创建自己的异常,但继承自一个内置的异常,它尽可能接近您想要的。
如果您需要捕获那个特定的错误,有一个名称是很有帮助的。
- 停止编写类和自定义异常-pyvideo.org/video/880/stop-writing-classes
- @哈米什格鲁比扬那段录像很糟糕。当有人建议好好利用一门课时,他只是大喊:"不要用课。"太棒了。课程很好。但不要相信我的话。
- @罗伯特格兰特不,你不明白。这段视频并不是真正的"不要上课"。这是关于不要过于复杂的事情。
- @雷罗,你可能已经理智地检查了视频所说的内容,并将其转化为一个有味觉的、明智的替代信息,但这就是视频所说的内容,而那些没有很多经验和常识的人也会这样做。
- @罗伯特格兰特,据我所知,他是在反对类的坏用法,而不是反对类的任何用法(见第12:48分钟)。他还说,在回答第一个问题时,存在过度简化的风险。所以关键是找到一个平衡点,不是吗?
- @萨缪尔桑塔纳,就像我说的,每当有人举手说"X怎么样?"X是个好主意,他只是说,"别再上别的课了。"很清楚。我同意关键是平衡;问题是,这太含糊了,无法实际生活在:—)
- 不完全是OP想要标记的。参数的值可能是正确的,但参数的组合是问题所在。所以非法言论不是正确的词,坏人论据更像这样。我认为这个想法太多了,所以我会提出一个不同的答案。
我只见过这种情况下使用的内置ValueError。
我认为处理这一问题的最佳方法是Python本身处理它的方式。python引发类型错误。例如:
1 2 3 4
| $ python -c 'print(sum())'
Traceback (most recent call last):
File"<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0 |
我们的初级开发人员刚刚在谷歌搜索"python exception wrong arguments"时发现了这个页面,我很惊讶,自这个问题被问到以来的十年里,这个显而易见的(对我来说)答案从未被提出过。
我不确定我是否同意从ValueError继承——我对文档的解释是ValueError只应该由内置的从中继承或自己抚养似乎是不正确的。
Raised when a built-in operation or
function receives an argument that has
the right type but an inappropriate
value, and the situation is not
described by a more precise exception
such as IndexError.
--值错误文档
- 内置操作或功能..
- 比较google.com/codesearch?Q=lang:python+class+werror&40;([^e]&zwnj;&8203;w*e[^x]w)&41;:使用google.com/codesearch?Q=lang:python+class+w*错误&40;exce&zwnj;&8203;选项&41;:
- @DBR:是的,我认为它们的意思是"(内置操作或功能)",而不是"(内置操作)或功能"。我想他们会在第二种情况下说"用户定义"来对比它。
- @这很有趣,google.com/codesearch也是如此?q=lang%3aphython+class+illegalargument&zwnj;&8203;exception--它们在从valueerror、exception和baseexception继承之间进行拆分。
- 这一宣传只意味着内置程序可以提升它,而不是只有内置程序可以提升它。在本例中,对于Python文档来说,讨论外部库会产生什么并不完全合适。
- 我所见过的每一个python软件都使用ValueError来处理这类事情,所以我认为您试图对文档进行过多的阅读。
- @JamesBennett:我们在上面的谷歌代码搜索中引用了几个不直接使用ValueError的项目,所以至少需要澄清。
- 呃,如果我们要用谷歌代码搜索来证明这一点:google.com/codesearch?Q=lang%3aphython+raise%5C+valueerror 66300例raising valueerror,包括zope、xen、django、mozilla(这只是第一页的结果)。如果适合内置异常,请使用它。
- 如前所述,文档不明确。它应该写为"当内置操作或内置函数接收时引发"或"当函数或内置操作接收时引发"。当然,不管最初的意图是什么,当前的实践已经战胜了它(正如@dbr指出的那样)。所以应该把它改写成第二个变量。
- 这应该是一个评论而不是回答。
- 引用的文档不会阻止您在用户编写的代码中引发ValueError。在Python社区中广泛使用的是在自己的代码中使用。
同意Markus提出的滚动您自己的异常的建议,但是异常的文本应该澄清问题在参数列表中,而不是单个参数值中。我提议:
1 2
| class BadCallError(ValueError):
pass |
当缺少特定调用所需的关键字参数或参数值单独有效但彼此不一致时使用。当特定参数类型正确但超出范围时,ValueError仍然是正确的。
这难道不是Python中的标准异常吗?
一般来说,我希望python样式在区分函数的错误输入(调用者的错误)和函数中的错误结果(我的错误)方面更为清晰。所以也可能存在badArgumentError来区分参数中的值错误和局部变量中的值错误。
- 如果找不到关键字,我会提高KeyError(因为缺少的显式关键字在语义上与缺少该关键字的**kwargsdict相同)。