如何写所有2^N布尔条件(python)的if语句

问题描述:

我有一个函数,需要根据输入的查询实例执行查询.. 但随着条件的增加,对我来说变得单调乏味列出他们全部。 例如: 假设我有两个条件最初:如何写所有2^N布尔条件(python)的if语句

if (cond_1 == True and cond_2 == False): 
    do something 
elif cond_1 == True and cond_2 == True: 
    do something else 
elif cond_1 == False and cond_2 == True: 
    do this 

....

所以我想,如果条件发生在二进制值然后有2^N语句我必须写:(

所以现在我有3个条件变量(8个报表)..我恐怕这个数字可能在将来增加。 是tehre更好的方法来检查这些条件?

+3

相关:http://*.com/questions/4726949/python-elegant-assignment-based-on-true-false-values – 2012-03-01 23:05:24

+0

如果你想在所有这些情况下做其他事情,那么现在有方式为每个案例写一份声明,对吗? – 2012-03-01 23:06:15

+4

'== True'和'== False'几乎总是一个(文体)错误。使用'cond_1而不是cond_2)'等 – 2012-03-01 23:07:47

待办事项ÿ你需要总是写出所有2^n种可能性吗?

而且是所有的东西,你必须做不同的(因此也是2^n项操作?)

不过我可以给一些提示:

不要使用“== true”或“==假”

你写什么等于:

if cond_1 and not cond_2: 
    do something 
elif cond_1 and cond_2: 
    do something else 
elif not cond_1 and cond_2: 
    do this 

想想也写:

if cond_1: 
    if cond_2: 
     Do something 
    else: 
     Do something 
else: 
    if cond_2: 
     Do something 
    else: 
     Do something 

您还可以根据值定义功能:

def __init__(self): 
    self.actions = { 
     (False, False): action_1, 
     (False, True): action_2, 
     ... 
    } 

def action_1(self): 
    some action 

def action_2(self): 
    some action 

.... 

,并称之为:

self.actions[(cond_1, cond_2)]() 

如果你想优化的情况下,期权的数量,您有类似的不同条件行动,看看卡诺图(看起来比它容易):

http://en.wikipedia.org/wiki/Karnaugh_map

+2

KICE地图上的NICE提示,从来没有想到过它们(这是我看过它们以来的一个长时间) – 2012-03-01 23:30:25

+1

卡诺拉地图= 1年CS恶梦 – UmNyobe 2012-03-07 15:52:56

+0

实际我喜欢这些地图......非常简单而有趣,可以简化复杂的布尔表达式。 – 2012-03-07 16:51:28

您应该never test a boolean variable with == True or == False。相反,只需使用布尔值就足够了。如果你想掩盖真值的几乎每一个组合,你可能还需要嵌套,就像这样:

if cond_1: 
    if cond_2: 
     do something 
    else: 
     do something else 
elif cond_2: 
    do this 

如果数量比进一步增加,我建议的地图,像这样:

call_map = { 
    (True, True, True): func1, 
    (True, False, True): func2, 
    (True, False, False): func3, 
} 
try: 
    func = call_map[(cond_1, cond_2, cond_3)] 
except KeyError: 
    pass 
else: 
    func() 

但是,请注意,大量不同的情况是肯定的代码异味。几乎在任何情况下,实际上并不需要这么多的情况,并且实际上可以直接调用一个函数。你可能认为你的情况是个例外,但事实并非如此。你为什么需要这么多案件?

+1

“你不应该用== True或== False测试一个布尔变量” - 除了可读性/样式考虑之外,省略显式提及True和False的比较也更安全。如果x的值等于名为'True'的对象引用的值(可以重新定义,尽管非常糟糕的做法),那么说'if x == True'就是测试。如果x在布尔上下文中评估,则评估为布尔值True(这正好是*所预期的)。 – 2012-03-01 23:41:45

我会使用一个词典以更清晰的方式将条件映射到动作。如果你真的需要为每种情况做不同的事情,那么可能没有比列举可能性更好的方法。

def do_something(): 
    pass 

def do_something_else(): 
    pass 

def do_this(): 
    pass 


do_dict = {(True, False): do_something, 
      (True, True): do_something_else, 
      (False, True): do_this} 

# call it 
do_dict[(cond_1, cond_2)]() 

如果你的目标是避免编写大量“阿富汗国家发展战略”和布尔表达式,你可以使用质数,只有一个条件,像这样(例如2个条件)

cond = (2**cond_1)*(3**cond_2) 

所以

cond == 1 #means cond_1 and cond_2 are False 
cond == 2 #means cond_1 is True and con_2 is False 
cond == 3 #means cond_1 is False and con_2 is True 
cond == 6 #means con_1 and Con_2 are True 

这个技巧可用于3种条件下使用3张素等

+0

你是对的,我错了,我的坏:(猜猜这意味着我应该停止对今晚的主持。对不起,这两个问题恢复和(现在)误导评论删除。 – 2012-03-02 00:13:50

+0

对不起,我的观点是,你可以概括如果有任何问题,请填写任意数量的条件,对不起,如果有任何问题,请让我知道您的决定以及我是否有错误 – ChessMaster 2012-03-02 00:14:38

+0

不,我错了,我将乘法与加法混淆了,我正在考虑沿着二进制值的例子。你的是几乎相同的,但也不同,所以它的优点。忘记我曾经开过我的鼻子到你的两个答案:) – 2012-03-02 00:15:47

可以采取N大小的条件列表中,并把它转换成一个单一的值进行比较,通过将条件成2.

>>> conditions = [True, False, True, True, False] 
>>> condition = sum(2**i * cond for i, cond in enumerate(conditions)) 
>>> condition 
13 

倍数的条件的第一个值是2^0 = 1的总和,第二是2^1 = 2,第三被2^2 = 4, ...分别乘以真值(1如果True,0如果False)。

这还允许您查看条件的子集是否为真。如果您需要了解的情况,至少一个子集是真实的,你可以使用二进制&找出:

>>> subset = lambda c, x: (c & x) == x 
>>> conditions = [True, False, True, True, False, True, True, True, True] 
>>> condition = sum(2**i * cond for i, cond in enumerate(conditions)) 
>>> subset(condition, 13) 
True 
>>> subset(condition, 2) 
False 

具有由以前的一些答案的提供的功能,而不是使用字典,你也可以使用列表和字典来将条件映射到行为。您也可以实现defaultdict样的功能与列表(虽然使用2^n个存储器,而且很可能不是最好的主意):

def do_something(): 
    print("Hello World!") 
condition_action_map = [None] * (2 ** len(conditions)) 
condition_action_map[13] = do_something 

你可能会想如果你使用的东西彻底评论此喜欢这个。

您正在寻找一种简洁的方式来写出真值表。 (你的唯一选择就是找到一种方法,使用布尔代数来简化你的表情;用简单的形式可能不存在。)有没有办法让这个简单,除了以节省打字:

def TruthTable(text): 
    table = {} 

    for line in text.splitlines(): 
     line = line.strip() 
     if line: 
      inputs,output = line.split() 
      table[tuple(bool(int(x)) for x in inputs)] = bool(int(output)) 

    return lambda *inputs:table[inputs] 

演示:

myFunc = TruthTable(''' 
    000 1 
    001 0 
    010 0 
    011 1 
    100 1 
    101 0 
    110 0 
    111 1 
''') 

输出:

>>> myFunc(False, False, True) 
False 

如果你需要比布尔输出的更多,你可以适应ŧ他通过使用例如字典指任意表达式,和后处理的按键为布尔值的元组:

{ 
    (0,0,0): <expr0>, 
    (0,0,1): <expr1>, 
    (0,1,0): <expr2>, 
    (0,1,1): <expr3>, 
    ... 
} 

你也可以做它用二进制表示如下(如0b110 == 6),但我觉得它更干净:

{ 
    0b000: <expr0>, 
    0b001: <expr1>, 
    ... 
} 

你甚至可以只使用它你以后转换成字典快速查找(做dict((intToBinarytuple(i),expr) for i,expr enumerate(myList)))的列表:

[ 
      # ABC 
    <expr0>, # 000 
    <expr1>, # 001 
    <expr2>, # 010 
    <expr3>, # 011 
    ... 
] 

旁注:万一你需要任意的python命令,你可以像这样调度:

conditions = (True, False, True) 

c = lambda *args: conditions==toBooleanTuple(args) 
if c(0,0,0): 
    ... 
elif c(0,0,1): 
    ... 
elif c(0,1,0): 
    ... 
elif c(0,1,1): 
    ... 
+0

有趣的:)很不错的逻辑 – Fraz 2012-03-02 01:33:00