Python: 如果三个条件中有多个为真,则返回假
我正在写一个django模型,让我的网站可以使用优惠券。
优惠券可以有三种类型:终身账户券、特定月份的券和特定金额的券。
为了简单起见,我只允许优惠券有这三种可能的值中的一种(也就是说,一个优惠券不能同时是10美元和5个月的券)。但是我想在保存优惠券的时候检查一下,确保这个规则是正确的。
目前我有:
true_count = 0
if self.months:
true_count += 1
if self.dollars:
true_count += 1
if self.lifetime:
true_count += 1
if true_count > 1:
raise ValueError("Coupon can be valid for only one of: months, lifetime, or dollars")
我知道有更好的方法来做到这一点,但我现在想不出来(可以说是程序员的瓶颈)。
非常感谢任何帮助。
如果有用的话,这三种类型分别是整数、整数和布尔值。
months = models.IntegerField(default=0)
cents = models.IntegerField(default=0)
#dollars = models.FloatField(default=0.00)
#dollars replaced with integer cents per advice of group
lifetime = models.BooleanField(default=False)
11 个回答
2
if (self.months && (self.dollars || self.lifetime)) || (self.dollars && (self.months || self.lifetime)) || (self.lifetime && (self.dollars || self.months))
raise ValueError("Coupon can be valid for only one of: months, lifetime, or dollars")
编辑:
我用卡诺图(Karnaugh map)做了个快速的电路简化(可以参考这个链接:http://en.wikipedia.org/wiki/Karnaugh_map)。最后得出的结果是,这个是用布尔逻辑能得到的最小函数:
if((self.months && self.dollars) || (self.dollars && self.lifetime) || (self.lifetime && self.months))
raise ValueError("Coupon can be valid for only one of: months, lifetime, or dollars")
从逻辑上讲,我的两个说法是等价的,但第二个在技术上更快/更高效。
编辑 #2:如果有人感兴趣,这里是卡诺图的结果
A | B | C | f(A, B, C)
----------------------
0 | 0 | 0 | 0
----------------------
0 | 0 | 1 | 0
----------------------
0 | 1 | 0 | 0
----------------------
0 | 1 | 1 | 1
----------------------
1 | 0 | 0 | 0
----------------------
1 | 0 | 1 | 1
----------------------
1 | 1 | 0 | 1
----------------------
1 | 1 | 1 | 1
简化为:
C\AB
-----------------
| 0 | 0 | 1 | 0 |
----------------- OR AB + BC + AC
| 0 | 1 | 1 | 1 |
-----------------
5
你也可以用列表推导式来过滤掉那些假的值:
if len([x for x in [self.months, self.dollars, self.lifetime] if x]) > 1:
raise ValueError()
或者可以参考一下MRAB的回答来进行扩展:
if sum(map(bool, [self.months, self.dollars, self.lifetime])) > 1:
raise ValueErrro()
13
在类似的情况下,我做过的一件事是这样的:
coupon_types = (self.months, self.dollars, self.lifetime,)
true_count = sum(1 for ct in coupon_types if ct)
if true_count > 1:
raise ValueError("Coupon can be valid for only one of: months, lifetime, or dollars")
现在将来添加新的优惠券类型来检查变得简单多了!