基于True/False值的Python优雅赋值

exu*_*ero 28 python if-statement boolean

我有一个我想要设置的变量,具体取决于三个布尔值中的值.最直接的方式是if语句后跟一系列elifs:

if a and b and c:
    name = 'first'
elif a and b and not c:
    name = 'second'
elif a and not b and c:
    name = 'third'
elif a and not b and not c:
    name = 'fourth'
elif not a and b and c:
    name = 'fifth'
elif not a and b and not c:
    name = 'sixth'
elif not a and not b and c:
    name = 'seventh'
elif not a and not b and not c:
    name = 'eighth'
Run Code Online (Sandbox Code Playgroud)

这有点尴尬,我想知道是否有更多的Pythonic方法来处理这个问题.想到了几个想法.

  1. 字典黑客:

    name = {a and b and c: 'first',
            a and b and not c: 'second',
            a and not b and c: 'third',
            a and not b and not c: 'fourth',
            not a and b and c: 'fifth',
            not a and b and not c: 'sixth',
            not a and not b and c: 'seventh',
            not a and not b and not c: 'eighth'}[True]
    
    Run Code Online (Sandbox Code Playgroud)

我把它称之为黑客,因为我并不太疯狂,因为我认为其中七个键是假的并且相互重叠.

  1. 和/或魔术

    name = (a and b and c and 'first' or
            a and b and not c and 'second' or
            a and not b and c and 'third' or
            a and not b and not c and 'fourth' or
            not a and b and c and 'fifth' or
            not a and b and not c and 'sixth' or
            not a and not b and c and 'seventh' or
            not a and not b and not c and 'eighth')
    
    Run Code Online (Sandbox Code Playgroud)

这是有效的,因为Python ands和ors返回要评估的最后一个值,但你必须知道这是为了理解这个奇怪的代码.

这三个选项都不令人满意.您有什么推荐的吗?

Cli*_*ler 50

您可以将a,b和c视为三位,当它们组合在一起形成0到7之间的数字.然后,您可以得到一个值数组['first','second',...'eight' ]并使用位值作为数组的偏移量.这只是两行代码(一行用于将位组装成0-7的值,一行用于查找数组中的值).

这是代码:

nth = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)]
Run Code Online (Sandbox Code Playgroud)

  • @Sven它是,是的,这是可能的:`nth [(a和4)|(b和2)|(c和1)]`效果很好. (4认同)
  • 你不能放弃`或0`部分吗? (3认同)

Tim*_*ker 29

用dict怎么样?

name = {(True, True, True): "first", (True, True, False): "second",
        (True, False, True): "third", (True, False, False): "fourth",
        (False, True, True): "fifth", (False, True, False): "sixth",
        (False, False, True): "seventh", (False, False, False): "eighth"}

print name[a,b,c] # prints "fifth" if a==False, b==True, c==True etc.
Run Code Online (Sandbox Code Playgroud)

  • +1 Simple比复杂更好.将这些位编码为int可能看起来很聪明,但最后它只是一个不必要的额外步骤. (12认同)
  • @OzcarRyz如果它增长,我会考虑使用二进制来生成*表*时生成键,但保持查找结构不变.它确实是这种自然数据结构. (2认同)

Sve*_*ach 11

也许不是更好,但怎么样

results = ['first', 'second', 'third', 'fourth', 
           'fifth', 'sixth', 'seventh', 'eighth']
name = results[((not a) << 2) + ((not b) << 1) + (not c)]
Run Code Online (Sandbox Code Playgroud)

  • 不是我的downvote,但它很难阅读和高度魔力.如果其他任何人都应该阅读代码,我肯定会建议不要这样做. (2认同)
  • 奇怪,这对我来说很好.我认为它很聪明,但不是过于聪明或危险的巫术.+1. (2认同)

eyq*_*uem 5

如果a,b,c真的是布尔值:

li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
name = li[a*4 + b*2 + c]
Run Code Online (Sandbox Code Playgroud)

如果他们不是布尔人:

li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
a,b,c = map(bool,(a,b,c))
name = li[a*4 + b*2 + c]
Run Code Online (Sandbox Code Playgroud)

克林特米勒的想法