Python中如何使用与或运算符?
我正在想办法验证表单中的字段。我决定可以给每个字段传入一组验证器,比如:
Field(validators=[email_validator, required_validator])
但我又想到,如果你想把这些验证器用或
的方式组合在一起,而不是用和
的方式呢?比如,一个字段可以接受加拿大的邮政编码,或者美国的邮政编码。当然,我可以创建一个新的验证器来接受这两种情况,但如果能让用户自己选择,那就更好了。
有没有可能我可以用位运算符来实现这个呢?
Field(validators = required&(postal_code|zip_code))
还是说我只是把事情搞得太复杂,反而给自己带来麻烦?
4 个回答
你需要在你的验证器类里实现两个方法:__or__(self, other) 和 __and__(self, other)。这两个方法可以让你的验证器动态地返回一个新的验证器,这个新的验证器知道怎么去完成相应的工作。简单来说,你的验证器应该能够以这种方式动态组合在一起(比如,如果它们是用正则表达式来工作的,并且你可以对正则表达式的写法做一些假设,那么你就可以在返回的新验证器中适当地组合这些正则表达式)。
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
sqlobject使用了类似这样的方式,下面是一个例子:
MyTable.select((MyTable.q.name == "bob") | (MyTable.q.age == 5))
这种方法的主要问题是运算符的优先级。为了让代码看起来更整洁,需要用更多的括号。一个更好的方法是使用 And() 和 Or() 函数,并采用前缀表示法,而不是中缀表示法。这样做的好处是,新的程序员在阅读你的代码时更容易理解。
在你上面的例子中,我建议可以这样写:
Field(validators=[required, Or(postal_code, zip_code)])
这里列表中的所有验证器都是隐式地用 And 连接在一起的。这让简单的情况变得容易(简单情况指的是“匹配所有这些验证器”),同时也能处理比较复杂的表达式,比如:
Field(validators=Or(And(IsAmerica(), zip_code),
And(Not(IsAmerica()), city))])
当然,这只是一个建议。如上所示,在某些系统中(比如 Django 和 sqlobject),使用 & 和 | 也能很好地工作。你可以清楚地看到,在我的例子中,复杂的情况会因为有很多层的括号而变得麻烦,这也是你需要考虑的权衡。
Django通过使用Q
对象来解决这个问题,这些对象可以用&
和|
来组合,从而创建更复杂的条件。模仿他们的用法可能是一个可行的解决方案。