我发现自己一直在编写相同的参数检查代码来进行数字运算:
def myfun(a, b):
    if a < 0:
        raise ValueError('a cannot be < 0 (was a=%s)' % a)
    # more if.. raise exception stuff here ...
    return a + b有没有更好的方法?我被告知不要对这些事情使用'assert‘(尽管我看不出问题,除了不知道导致错误的变量的值)。
编辑:为了澄清,参数通常只是数字,错误检查条件可以是复杂的、非平凡的,并且不一定会导致稍后的异常,而只是导致错误的结果。(不稳定的算法,无意义的解决方案等)
发布于 2009-10-29 12:24:59
如果你使用python -O运行,assert会得到优化(适度的优化,但有时很好)。如果您有经常重复的模式,一个更好的替代方案可能是使用装饰器--这是排除重复的好方法。例如,假设您有大量的函数,这些函数必须使用参数by-position (而不是by-keyword)调用,并且它们的第一个参数必须为正;然后...:
def firstargpos(f):
  def wrapper(first, *args):
    if first < 0:
      raise ValueError(whateveryouwish)
    return f(first, *args)
  return wrapper然后你可以这样说:
@firstargpos def myfun(a,b):...
并且检查将在装饰器(或者更确切地说,它返回的包装器闭包)中一次性执行。因此,唯一棘手的部分是弄清楚你的函数到底需要什么检查,以及如何最好地调用装饰器来表达这些(很难说,因为没有看到你定义的函数集和每个函数需要的检查集!)。请记住,DRY (“不要重复自己”)在软件开发的指导原则中名列前茅,Python有合理的支持来允许您实现DRY并避免boilerplatey、重复的代码!-)
发布于 2009-10-29 12:21:10
您不希望使用assert,因为您的代码可以以这样一种方式运行(在某些系统上是默认的),即不检查assert行,也不会引发错误(-O命令行标志)。
如果你使用的很多变量都应该具有相同的属性,为什么不子类化你正在使用的任何类型,并将检查添加到类本身呢?然后,当你使用你的新类时,你知道你永远不会有一个无效值,也不需要到处去检查它。
发布于 2009-10-29 12:44:48
我不确定这是否能回答你的问题,但我突然意识到,在函数开始时检查大量参数并不是很有效。
我这样说的意思是,这是大多数pythonistas的假设,我们都是同意的成年人,我们相互信任,不会做傻事。下面是我如何写你的例子的:
def myfun(a, b):
    '''a cannot be < 0'''
    return a + b这有三个明显的优点。首先,它很简洁,没有额外的代码做任何与你实际想要完成的事情无关的事情。其次,它将信息准确地放在它所属的help(myfun)中,pythonistas应该在那里查找用法说明。最后,a的非正值真的是一个错误吗?尽管你可能会这样认为,除非当a为零时某些东西肯定会崩溃(这里可能不会),然后让它滑过并导致调用流上的错误是更明智的。毕竟,如果a + b出错,它会引发一个异常,该异常会在调用堆栈中向上传递,并且行为基本相同。
https://stackoverflow.com/questions/1641591
复制相似问题