如何根据值testing多个variables?

我试图做一个函数,将多个variables比较为一个整数,并输出一个三个字母的string。 我想知道是否有办法将其转换为Python。 所以说:

x = 0 y = 1 z = 3 mylist = [] if x or y or z == 0 : mylist.append("c") if x or y or z == 1 : mylist.append("d") if x or y or z == 2 : mylist.append("e") if x or y or z == 3 : mylist.append("f") 

这将返回一个列表

 ["c", "d", "f"] 

是这样的可能吗?

你误解了布尔expression式是如何工作的。 他们不会像英文句子一样工作,并猜测你在这里谈论所有名字的相同比较。 您正在寻找:

 if x == 1 or y == 1 or z == 1: 

否则xy会自行评估(如果为0 ,则为False ,否则为True )。

你可以缩短到:

 if 1 in (x, y, z): 

或更好:

 if 1 in {x, y, z}: 

使用一set来利用恒定成本的成员资格testing(无论左手操作数是多less,都需要一定的时间)。

当你使用or ,python将运算符的每一侧视为单独的expression式。 expression式x or y == 1被视为x第一个布尔testing,那么如果它是False,则testingexpression式y == 1

这是由于运营商的优先权 。 or运算符的优先级低于==testing,所以后者首先被评估。

但是,即使情况并非如此,expression式x or y or z == 1实际上被解释为(x or y or z) == 1 ,但是这仍然不能达到你期望的效果。

x or y or z会计算出第一个参数“truthy”,例如not False ,numeric 0或者空值(关于Python在布尔上下文中认为false的细节,请参考布尔expression式 )。

所以对于值x = 2; y = 1; z = 0 x = 2; y = 1; z = 0 x = 2; y = 1; z = 0x or y or z将parsing为2 ,因为这是参数中第一个类似于真的值。 那么2 == 1将是False ,即使y == 1将是True

反过来也一样。 针对单个variablestesting多个值; x == 1 or 2 or 3会出于同样的原因失败。 x in {1, 2, 3}使用x == 1 or x == 2 or x == 3x in {1, 2, 3}

你的问题更容易用字典结构解决,如:

 x = 0 y = 1 z = 3 d = {0: 'c', 1:'d', 2:'e', 3:'f'} mylist = [d[k] for k in [x, y, z]] 

以前的解决scheme:正如Martijn Pieters所说,正确和最快的格式是:

 if 1 in {x, y, z}: 

似乎没有解决的一个主要问题是,你希望你的输出列表包含每个字母后真正的if语句。

只使用Martijn Pieters的build议,你现在可以:

 if 0 in {x, y, z}: Mylist.append("c") elif 1 in {x, y, z}: Mylist.append("d") ... 

问题:第一个if语句将返回true,并且永远不会得到以下elif语句。 所以你的清单会简单地返回:

 ["c"] 

你想要的是有单独的if语句,以便python将读取每个语句,无论前者是真的还是假的。 如:

 if 0 in {x, y, z}: Mylist.append("c") if 1 in {x, y, z}: Mylist.append("d") if 2 in {x, y, z}: Mylist.append("e") ... 

这将起作用,但是如果你习惯于使用字典(看看我在那里做了什么),你可以通过初始字典将数字映射到你想要的字母来进行清理,然后使用'for'循环:

 numToLetters = {0:"c", 1:"d", 2:"e", 3:"f"} for number in numToLetters: if number in {x, y, z}: Mylist.append(numToLetters[number]) 

直接写x or y or z == 0

 if any(map((lambda value: value == 0), (x,y,z))): pass # write your logic. 

但我不认为,你喜欢它。 :)这种方式是丑陋的。

另一种方式(更好)是:

 0 in (x, y, z) 

顺便说一句, if可以写成这样的东西

 my_cases = { 0: Mylist.append("c"), 1: Mylist.append("d") # .. } for key in my_cases: if key in (x,y,z): my_cases[key]() break 

如果你非常懒,你可以把值放在一个数组中。 如

 list = [] list.append(x) list.append(y) list.append(z) nums = [add numbers here] letters = [add corresponding letters here] for index in range(len(nums)): for obj in list: if obj == num[index]: MyList.append(letters[index]) break 

你也可以把数字和字母放在字典中,但是这可能比简单的语句复杂得多。 这就是你想得到额外的懒惰:)

还有一件事,你的

 if x or y or z == 0: 

将编译,但不是你想要的方式。 当你简单地把一个variables放在if语句中(例子)

 if b 

程序将检查variables是否不为空。 另一种方式来写上述语句(这更有意义)是

 if bool(b) 

Bool是一个内置的python函数,它基本上是validation一个布尔语句的命令(如果你不知道这是什么,那么这就是你现在要做的if语句:)

我发现另一个懒惰的方式是:

 if any([x==0, y==0, z==0]) 

要检查一组variables中是否包含一个值,可以使用内置模块itertoolsoperator

例如:

import:

 from itertools import repeat from operator import contains 

声明variables:

 x = 0 y = 1 z = 3 

创build值的映射(按照您要检查的顺序):

 check_values = (0, 1, 3) 

使用itertools来允许重复的variables:

 check_vars = repeat((x, y, z)) 

最后,使用map函数来创build一个迭代器:

 checker = map(contains, check_vars, check_values) 

然后,在检查值时(按原始顺序),使用next()

 if next(checker) # Checks for 0 # Do something pass elif next(checker) # Checks for 1 # Do something pass 

等等…

这比lambda x: x in (variables)有一个优势,因为operator是一个内置模块,比使用lambda创build一个自定义就地function更快,更高效。

另一种检查列表中是否有非零(或False)值的选项:

 not (x and y and z) 

当量:

 not all((x, y, z)) 

我认为这会更好地处理:

 my_dict = {0: "c", 1: "d", 2: "e", 3: "f"} def validate(x, y, z): for ele in [x, y, z]: if ele in my_dict.keys(): return my_dict[ele] 

输出:

 print validate(0, 8, 9) c print validate(9, 8, 9) None print validate(9, 8, 2) e 

如果你想使用if语句,else语句是另一个解决scheme:

 myList = [] aList = [0,1,3] for l in aList: if l==0:myList.append('c') elif l==1:myList.append('d') elif l==2:myList.append('e') elif l==3:myList.append('f') print(myList) 
 d = {0:'c', 1:'d', 2:'e', 3: 'f'} x, y, z = (0, 1, 3) print [v for (k,v) in d.items() if x==k or y==k or z==k] 

此代码可能会有所帮助

 L ={x, y, z} T= ((0,"c"),(1,"d"),(2,"e"),(3,"f"),) List2=[] for t in T : if t[0] in L : List2.append(t[1]) break; 

Set是这里的好方法,因为它命令variables,这里你的目标似乎是什么。 无论参数的顺序如何{z,y,x}都是{0,1,3}

 >>> [chr(ord('c')+i) for i in {z,x,y}] ['c', 'd', 'f'] 

与数字相对应的字母在这里由chr(ord('c')+i) ,其中chrord是字符和数字代码之间的桥梁。

所以整个解决scheme是O(n)。

这里提供的所有优秀答案集中在原始海报的具体要求上,集中在Martijn Pieters提出的if 1 in {x,y,z}解中的if 1 in {x,y,z}
他们忽视的是这个问题的更广泛的含义:
我如何testing一个variables对多个值?
如果使用string,提供的解决scheme不适用于部分匹配:
testingstring“Wild”是否有多个值

 >>> x="Wild things" >>> y="throttle it back" >>> z="in the beginning" >>> if "Wild" in {x,y,z}: print (True) ... 

要么

 >>> x="Wild things" >>> y="throttle it back" >>> z="in the beginning" >>> if "Wild" in [x,y,z]: print (True) ... 

对于这种情况,最简单的方法就是转换成string

 >>> [x,y,z] ['Wild things', 'throttle it back', 'in the beginning'] >>> {x,y,z} {'in the beginning', 'throttle it back', 'Wild things'} >>> >>> if "Wild" in str([x,y,z]): print (True) ... True >>> if "Wild" in str({x,y,z}): print (True) ... True 

一行解决scheme:

 mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)] 

要么:

 mylist = ['cdef'[i] for i in range(4) if i in (x, y, z)] 

不要太复杂,只要按照最简单的方法。

  x = 0 y = 1 z = 3 Mylist = [] if x == 0 or y==0 or z==0: Mylist.append('c') elif x == 1 or y == 1 or z==1: Mylist.append('d') elif x==2 or y==2 or z==2: Mylist.append('e') elif x==3 or y==3 or z==3: Mylist.append('f') 

干杯!