3

我发现自己一直在为数字运算编写相同的参数检查代码:

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

有没有更好的办法?我被告知不要对这些事情使用“断言”(尽管我没有看到问题,除了不知道导致错误的变量的值)。

编辑:为了澄清,参数通常只是数字,错误检查条件可能很复杂,不平凡,以后不一定会导致异常,而只会导致错误的结果。(不稳定的算法,无意义的解决方案等)

4

3 回答 3

4

assert如果您使用python -O(适度的优化,但有时很高兴)运行,则会得到优化。如果您有经常重复的模式,一种更可取的选择可能是使用装饰器——排除重复的好方法。例如,假设您有无数个函数,必须按位置(而不是按关键字)调用参数,并且它们的第一个参数必须为正;然后...:

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 并避免样板、重复的代码!-)

于 2009-10-29T04:24:58.580 回答
0

您不想使用断言,因为您的代码可以以不检查断言行并且不引发错误(-O命令行标志)的方式运行(并且默认情况下在某些系统上)。

如果您使用的许多变量都应该具有相同的属性,为什么不将您使用的任何类型子类化并将该检查添加到类本身?然后当你使用你的新类时,你知道你永远不会有一个无效的值,也不必到处检查它。

于 2009-10-29T04:21:10.257 回答
-1

我不确定这是否会回答您的问题,但让我感到震惊的是,在函数开头检查很多参数并不是很pythonic

我的意思是大多数pythonistas假设我们都是同意的成年人,我们彼此信任不会做愚蠢的事情。这是我编写示例的方式:

def myfun(a, b):
    '''a cannot be < 0'''
    return a + b

这具有三个明显的优点。首先,它很简洁,实际上没有额外的代码可以做任何与您实际尝试完成的事情无关的事情。其次,它将信息准确地放在它所属的地方,在 中help(myfun),pythonistas 应该在其中查找使用说明。最后,非正值a真的是错误吗?尽管您可能会这么认为,除非如果 a 为零(这里可能不会),除非某些东西肯定会中断(这里可能不会),否则也许让它溜过并导致调用流中的错误更明智。毕竟,如果a + b出错,它会引发一个异常,该异常会被传递到调用堆栈并且行为仍然几乎相同。

于 2009-10-29T04:44:48.330 回答