如何断言N个给定参数中的零或只有一个被传递

时间:2009-10-30 10:11:55

标签: python

我有这样的定义

def bar(self, foo=None, bar=None, baz=None):
    pass

我想确保foo,bar,baz中最多有一个通过。我能做到

if foo and bar:
    raise Ex()

if foo and baz:
    raise Ex()
....

但是有一些更简单的东西。

6 个答案:

答案 0 :(得分:9)

怎么样:

 initialisers = [foo, bar, baz]
 if initialisers.count(None) < len(initialisers) - 1:
     raise Ex()

它只计算有多少None存在。如果他们都是None或者只有一个不是那么好,否则会引发异常。

答案 1 :(得分:6)

x!=None为非Nones返回True(其数值为1!),其中False(其数值为0)表示Nones。所以,

sum(x!=None for x in (foo, bar, baz))

是计算这些标识符中有多少绑定到非None值的最简单方法(并且您可以将其计数与1一样,就像其他答案一样,他们的获取计数的方式) 。这是一种非常通用的方法,而不是x!=None你可以使用任何感兴趣的严格bool谓词;例如,如果你有一堆整数,并想知道它们中有多少有3作为十进制表示的第一个数字,

sum(str(abs(x)).startswith('3') for x in (a, b, c, d, e))

也可以。

不要对“总结bool”感到不安:Python bool被明确定义为int的子类,恰好有两个具有特殊str / repr的实例,但其他行为与普通的0和1完全相同。有很好的实用性这种设计的原因和对bools进行算术运算的能力就是其中之一,所以请随意使用这种能力! - )

答案 2 :(得分:4)

尝试

 count = sum(map(lambda x: 0 if x is None else 1, (foo, bar, baz)))
 if count > 1:
     raise Ex()

None变为0,将所有内容变为1,然后将所有内容汇总起来。

答案 3 :(得分:2)

我的答案更简短,我最喜欢的python功能 - 装饰器:

def single_keyword(func):
    def single_keyword_dec(*args, **kw):
        if len(kw) > 1:
            raise Exception("More than one initializer passed: {0}".format(kw.keys()))
        return func(*args, **kw)
    return single_keyword_dec

@single_keyword
def some_func(self, foo=None, bar=None, baz=None):
    print foo, bar, baz

some_func(object, foo=0)
some_func(object, foo=0, bar=0)
#result
0 None None
Traceback (most recent call last):
  File "dec2.py", line 13, in <module>
    some_func(object, foo=0, bar=0)
  File "dec2.py", line 4, in single_keyword_dec
    raise Exception("More than one initializer passed: {0}".format(kw.keys()))
Exception: More than one initializer passed: ['foo', 'bar']

如果您需要区分'foo','bar','baz'和其他一些关键字,您可以制作类似的装饰器,它可以接受要限制的关键字列表,并使用它如下:@single_keyword('foo', 'bar', 'baz') < / p>

这样它的100%代码重用,不会反复输入相同的东西,并且你在函数中得到了合适的关键字,而不是一些模糊的字典。

答案 4 :(得分:1)

if len(filter(lambda x: x != None, locals().values())) > 1:
    raise Exception()

编辑解决亚历克斯的观点。

答案 5 :(得分:-1)

喜欢这个。

def func( self, **kw ):
    assert len(kw) == 1, "Too Many Arguments"
    assert kw.keys[0] in ( 'foo', 'bar', 'baz' ), "Argument not foo, bar or baz"