关于python:如何针对值测试多个变量?

How to test multiple variables against a value?

我正在尝试创建一个函数,将多个变量与一个整数进行比较,并输出一个由三个字母组成的字符串。我想知道是否有一种方法可以将其转换为python。所以说:

1
2
3
4
5
6
7
8
9
10
11
12
13
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")

它会返回一个列表

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

这样的事情有可能吗?


你误解了布尔表达式是如何工作的;它们不像英语句子那样工作,并且猜测你在这里谈论的所有名称的比较是相同的。您正在寻找:

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

xy单独进行评估(False,如果0True

您可以使用对元组的包含测试来缩短这个时间:

1
if 1 in (x, y, z):

或者更好:

1
if 1 in {x, y, z}:

使用set利用固定成本成员资格测试(in无论左边的操作数是什么,都需要固定的时间)。

当您使用or时,python将操作符的每一面视为单独的表达式。表达式x or y == 1首先被视为x的布尔检验,如果这是错误的,则测试表达式y == 1

这是由于操作员的优先权。or运算符的优先级低于==测试,因此首先对后者进行评估。

然而,即使情况并非如此,并且表达x or y or z == 1实际上被解释为(x or y or z) == 1,但这仍然不能达到您预期的效果。

x or y or z将对第一个"truthy"参数进行计算,例如not False、numeric 0或empty(有关python在布尔上下文中认为错误的内容,请参见布尔表达式)。

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

同样的情况也适用于反向;针对单个变量测试多个值;x == 1 or 2 or 3会因同样的原因失败。使用x == 1 or x == 2 or x == 3x in {1, 2, 3}


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

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


如Martijn Pieters所述,正确且最快的格式是:

1
if 1 in {x, y, z}:

根据他的建议,您现在可以使用单独的if语句,这样无论前者是True还是False,python都可以阅读每个语句。例如:

1
2
3
4
5
6
7
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循环来清除此问题:

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

x or y or z == 0的直接方法是

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

但我不认为,你喜欢。:)这样很难看。

另一个更好的方法是:

1
0 in (x, y, z)

顺便说一句,很多if可以这样写。

1
2
3
4
5
6
7
8
9
10
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


如果您非常懒惰,可以将值放入数组中。如

1
2
3
4
5
6
7
8
9
10
11
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语句复杂得多。这就是你努力变得特别懒惰的原因:)

还有一件事,你的

1
if x or y or z == 0:

将编译,但不会以您希望的方式编译。当您在if语句中简单地放入一个变量时(示例)

1
if b

程序将检查变量是否不为空。写上述语句的另一种方法(更合理)是

1
if bool(b)

bool是python中的一个内置函数,它基本上执行验证布尔语句的命令(如果您不知道这是什么,那么它就是您现在在if语句中要做的事情:)

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

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

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

例如:

进口:

1
2
from itertools import repeat
from operator import contains

声明变量:

1
2
3
x = 0
y = 1
z = 3

创建值映射(按要检查的顺序):

1
check_values = (0, 1, 3)

使用itertools允许变量重复:

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

最后,使用map函数创建迭代器:

1
checker = map(contains, check_vars, check_values)

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

1
2
3
4
5
6
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创建自定义就地功能更快、更高效。

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

1
not (x and y and z)

当量:

1
not all((x, y, z))


我认为这将更好地处理它:

1
2
3
4
5
6
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]

输出:

1
2
3
4
5
6
print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e

如果要使用if,则下面的else语句是另一种解决方案:

1
2
3
4
5
6
7
8
9
10
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)

在这里,set是一个很好的方法,因为它对变量进行排序,这似乎是您的目标。{z,y,x}{0,1,3},无论参数的顺序如何。

1
2
>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']

这样,整个解决方案就是O(n)。


这里提供的所有优秀答案都集中在原海报的具体要求上,集中在Martijn Pieters提出的if 1 in {x,y,z}解决方案上。他们忽略的是问题的更广泛含义:如何针对多个值测试一个变量?如果使用字符串,所提供的解决方案将不适用于部分命中,例如:测试字符串"wild"是否在多个值中

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

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

对于这种情况,最容易转换为字符串

1
2
3
4
5
6
7
8
9
10
11
12
>>> [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

但是,正如@codeforester所提到的,用这种方法会丢失单词boundries,如:

1
2
3
4
>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if"rot" in str(x): print(True)
...
True

3个字母rot在列表中组合存在,但不是作为单个单词存在。对"rot"的测试将失败,但如果其中一个列表项是"rot in hell",那也将失败。结果是,如果使用这个方法,请注意搜索条件,并注意它确实有这个限制。


1
2
3
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]

此代码可能有帮助

1
2
3
4
5
6
7
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;

一线解决方案:

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

或:

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

您可以尝试下面所示的方法。在此方法中,您可以自由指定/输入要输入的变量数量。

1
2
3
4
5
6
7
8
9
10
11
12
mydict = {0:"c", 1:"d", 2:"e", 3:"f"}
mylist= []

num_var = int(raw_input("How many variables?")) #Enter 3 when asked for input.

for i in range(num_var):
    ''' Enter 0 as first input, 1 as second input and 3 as third input.'''
    globals()['var'+str('i').zfill(3)] = int(raw_input("Enter an integer between 0 and 3"))
    mylist += mydict[globals()['var'+str('i').zfill(3)]]

print mylist
>>> ['c', 'd', 'f']


它可以很容易做到

1
2
for value in [var1,var2,var3]:
     li.append("targetValue")

也许您需要输出位集的直接公式。

1
2
3
4
5
x=0 or y=0 or z=0   is equivalent to x*y*z = 0

x=1 or y=1 or z=1   is equivalent to (x-1)*(y-1)*(z-1)=0

x=2 or y=2 or z=2   is equivalent to (x-2)*(y-2)*(z-2)=0

让我们映射到位:'c':1 'd':0xb10 'e':0xb100 'f':0xb1000

is c的关系(是"c"):

1
if xyz=0 then isc=1 else isc=0

如果公式https://youtu.be/kadkcgbgk0k,使用数学?列表=plni9xbpdzuamul8htsl6vtopqrrn3hhfp&;t=315

【C】:EDOCX1【10】

【D】:EDOCX1【11】

通过以下逻辑连接这些公式:

  • 逻辑and是方程的平方和。
  • 逻辑or是方程的乘积。

你会得到一个总方程求和,你有求和的总公式。

那么sum&1是c,sum&2是d,sum&4是e,sum&5是f

在此之后,您可以形成预定义的数组,其中字符串元素的索引将对应于就绪字符串。

array[sum]给了你字符串。


这对你有帮助。

1
2
3
4
5
6
7
8
9
10
11
12
13
def test_fun(val):
    x = 0
    y = 1
    z = 2
    myList = []
    if val in (x, y, z) and val == 0:
        myList.append("C")
    if val in (x, y, z) and val == 1:
        myList.append("D")
    if val in (x, y, z) and val == 2:
        myList.append("E")

test_fun(2);

用Python表示伪代码的最简单的方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
x = 0
y = 1
z = 3
mylist = []

if any(v == 0 for v in (x, y, z)):
    mylist.append("c")
if any(v == 1 for v in (x, y, z)):
    mylist.append("d")
if any(v == 2 for v in (x, y, z)):
    mylist.append("e")
if any(v == 3 for v in (x, y, z)):
    mylist.append("f")


看起来你在建造某种凯撒密码。

更普遍的方法是:

1
2
3
input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]

输出

1
['c', 'd', 'f']

不确定这是否是您的代码所期望的副作用,但是输出的顺序将始终被排序。

如果这是您想要的,可以将最后一行更改为:

1
sorted([chr(val + origo) for val in inputs])


用单个值测试多个变量:if 1 in {a,b,c}:

用一个变量来测试多个值:if a in {1, 2, 3}:


您可以使用字典:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
x = 0
y = 1
z = 3
list=[]
dict = {0: 'c', 1: 'd', 2: 'e', 3: 'f'}
if x in dict:
    list.append(dict[x])
else:
    pass

if y in dict:
    list.append(dict[y])
else:
    pass
if z in dict:
    list.append(dict[z])
else:
    pass

print list