我应该在Python中针对坏/非法参数组合提出哪个例外?

cdl*_*ary 496 python arguments exception

我想知道在Python中指示无效参数组合的最佳实践.我遇到过一些你有这样功能的情况:

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
Run Code Online (Sandbox Code Playgroud)

唯一令人烦恼的是,每个包装都有自己的,通常略有不同BadValueError.我知道在Java中存在java.lang.IllegalArgumentException- 是否很好理解每个人都将BadValueError在Python中创建自己的s或者是否有另一种首选方法?

dbr*_*dbr 548

我只会提出ValueError,除非你需要一个更具体的例外.

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")
Run Code Online (Sandbox Code Playgroud)

真的没有意义class BadValueError(ValueError):pass- 您的自定义类与ValueError的使用完全相同,那么为什么不使用它呢?

  • >"那么为什么不用那个呢?" - 特异性.也许我想要抓住一些外层"MyValueError",但不是任何/所有"ValueError". (61认同)
  • 是的,因此,特殊性问题的一部分是引发ValueError的地方.如果被调用函数喜欢你的参数但在内部调用math.sqrt(-1),则调用者可能会捕获ValueError,期望***参数不合适.也许你只是在这种情况下检查消息...... (7认同)
  • 如果错误出现在 NUMBER 参数上,对于具有可变参数数量的函数......例如参数必须是偶数个参数的函数,那么您应该引发 TypeError 以保持一致。并且不要创建自己的类,除非 a) 您有用例或 b) 您正在导出库以供其他人使用。过早的功能是代码的死亡。 (4认同)
  • 我不确定这个论点是否成立:如果有人调用`math.sqrt(-1)`,那么这是一个需要修复的编程错误.`ValueError`不是要在正常的程序执行中捕获,也不是从`RuntimeError`派生的. (2认同)

Mar*_*rot 96

我会继承 ValueError

class IllegalArgumentError(ValueError):
    pass
Run Code Online (Sandbox Code Playgroud)

有时候创建自己的异常更好,但是从内置的异常继承,尽可能接近你想要的.

如果您需要捕获该特定错误,那么拥有一个名称会很有帮助.

  • @HamishGrubijan视频很糟糕.当有人建议好好利用课程时,他只是咩咩叫"不要上课".辉煌.课程很好.[但不要相信我的话](http://lucumr.pocoo.org/2013/2/13/moar-classes/). (35认同)
  • 停止编写类和自定义异常 - http://pyvideo.org/video/880/stop-writing-classes (25认同)
  • @RayLuo你可能有理智 - 检查了视频的内容,并将其转换成了一个可爱的,明智的替代信息,但这就是视频所说的,而且那些没有太多经验和常识的人将会离开用. (13认同)
  • @RobertGrant不,你不明白.该视频实际上并不是"不使用类".这是关于不要过于复杂的事情. (12认同)
  • @SamuelSantana就像我说的那样,任何人都举起手来说"X怎么样?" 在那里,X是一个好主意,他只是说,"不要再上一堂课." 很清楚.我同意关键是平衡; 问题是实际生活过于模糊:-) (3认同)
  • @RobertGrant 据我了解,他反对类的不良使用,而不是反对类的任何使用(参见第 12:48 分钟)。他确实说过,在回答第一个问题时,过度简化是有风险的。所以关键是要找到平衡,不是吗? (2认同)

Glo*_*eye 25

这取决于参数的问题是什么。

如果参数的类型错误,则引发 TypeError。例如,当您获得一个字符串而不是那些布尔值之一时。

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")
Run Code Online (Sandbox Code Playgroud)

但是请注意,在 Python 中我们很少进行这样的检查。如果参数确实无效,一些更深层次的函数可能会为我们抱怨。如果我们只检查布尔值,也许某些代码用户稍后会向它提供一个字符串,因为知道非空字符串始终为 True。这可能会为他节省一个演员。

如果参数具有无效值,则引发 ValueError。这似乎更适合您的情况:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")
Run Code Online (Sandbox Code Playgroud)

或者在这种特定情况下,递归的真值意味着保存的真值。由于我认为这是从错误中恢复,您可能还想在日志中抱怨。

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最准确的答案。这显然被低估了(到目前为止有 7 票,包括我的)。 (2认同)

J B*_*nes 12

我认为处理这个的最好方法是python本身处理它的方式.Python引发了一个TypeError.例如:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0
Run Code Online (Sandbox Code Playgroud)

我们的初级开发人员刚刚在google搜索"python exception错误论点"中找到了这个页面,我很惊讶,自从提出这个问题以来,十年内没有人提出明显(对我而言)的答案.

  • 没什么让我感到惊讶的,但是我100%同意,如果传递给函数的某些参数的类型错误,则TypeError是正确的异常。如果变量的类型正确,但其内容和值没有意义,则可以使用ValueError。 (6认同)
  • 正如 @user3504575 和 @Nobody 所说,如果参数与函数签名不匹配(位置参数数量错误、名称错误的关键字参数、参数类型错误),则使用 TypeError ,但在函数调用时使用 ValueError与签名匹配,但参数值无效(例如,调用 `int('a')`)。[来源](https://docs.python.org/3/library/exceptions.html#TypeError) (3认同)
  • 您的示例调用不带参数的 sum() ,这是一个 TypeError ,但是当参数类型正确时,OP 担心参数值的“非法”组合。在这种情况下,“save”和“recurse”都是布尔值,但如果“recurse”是“True”,那么“save”不应该是“False”。这是一个“值错误”。我同意问题标题的某些解释将由“TypeError”来回答,但不适用于所提供的示例。 (3认同)

Eli*_*ght 9

我大多只看到ValueError在这种情况下使用的内置.


小智 9

在这种情况下,您很可能会使用ValueErrorraise ValueError()完整),但这取决于坏值的类型。例如,如果您创建了一个仅允许字符串的函数,而用户输入了一个整数,那么您就会TypeError改为输入整数。如果用户输入了错误的输入(意味着它具有正确的类型,但不符合某些条件), aValue Error将是您的最佳选择。ValueError 还可以用于阻止程序出现其他异常,例如,您可以使用 aValueError来阻止 shell 表单引发 a ZeroDivisionError,例如在此函数中:

def function(number):
    if not type(number) == int and not type(number) == float:
        raise TypeError("number must be an integer or float")
    if number == 5:
        raise ValueError("number must not be 5")
    else:
        return 10/(5-number)
Run Code Online (Sandbox Code Playgroud)

PS 有关 python 内置异常的列表,请访问此处: https: //docs.python.org/3/library/exceptions.html(这是官方的 python 数据库)