Python 如何针对单个值测试多个变量?
我试图创建一个函数,将多个变量与一个整数进行比较,并输出一个由三个字母组成的字符串。我想知道是否有办法将其翻译成Python。那么说:Python 如何针对单个值测试多个变量?,python,if-statement,comparison,match,boolean-logic,Python,If Statement,Comparison,Match,Boolean Logic,我试图创建一个函数,将多个变量与一个整数进行比较,并输出一个由三个字母组成的字符串。我想知道是否有办法将其翻译成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 =
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"]
这样的事情可能吗?您误解了布尔表达式的工作原理;它们不像一个英语句子,你猜这里所有名字的比较都是一样的。您正在寻找:
if x == 1 or y == 1 or z == 1:
否则,x和y将根据其自身进行计算,如果为0,则为False,否则为True
您可以使用针对以下各项的安全壳测试来缩短该时间:
或者更好:
if 1 in {x, y, z}:
使用以利用恒定成本成员身份测试,即in,无论左手操作数是什么,都会占用固定的时间
解释
使用or时,python会将运算符的每一侧视为单独的表达式。表达式x或y==1首先被视为x的布尔测试,如果为False,则测试表达式y==1
这是由于。or运算符的优先级低于==测试,因此先计算后者
然而,即使情况并非如此,表达式x或y或z==1实际上被解释为x或y或z==1,这仍然不会达到您期望的效果
x、y或z将计算为第一个参数“truthy”,例如not False、numeric 0或empty。有关Python在布尔上下文中认为False的内容的详细信息,请参阅
因此,对于x=2的值;y=1;z=0,x或y或z将解析为2,因为这是参数中的第一个类真值。那么2==1将为False,即使y==1将为True
这同样适用于相反的情况;针对单个变量测试多个值;x==1或2或3将因相同的原因失败。在{1,2,3}中使用x==1或x==2或x==3或x。写入x或y或z==0的直接方法是
但是我不认为你喜欢它
这条路很难看
另一种更好的方法是:
0 in (x, y, z)
顺便说一句,很多ifs都可以这样写
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
您的问题更容易通过以下字典结构解决:
x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]
要检查一个值是否包含在一组变量中,可以使用内置模块itertools和运算符 例如: 进口:
from itertools import repeat
from operator import contains
声明变量:
x = 0
y = 1
z = 3
check_vars = repeat((x, y, z))
values = {x, y, z}
if 0 in values:
mylist.append("c")
if 1 in values:
mylist.append("d")
按照要检查的顺序创建值映射:
check_values = (0, 1, 3)
使用itertools允许重复变量:
x = 0
y = 1
z = 3
check_vars = repeat((x, y, z))
values = {x, y, z}
if 0 in values:
mylist.append("c")
if 1 in values:
mylist.append("d")
最后,使用map函数创建迭代器:
checker = map(contains, check_vars, check_values)
然后,在按原始顺序检查值时,使用下一步:
等等
这比变量中的lambda x:x具有优势,因为运算符是一个内置模块,比使用lambda(必须创建自定义就地函数)更快、更高效
检查列表中是否存在非零值或假值的另一个选项:
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
In [21]: mylist
Out[21]: ['c', 'd', 'f']
如果要使用If、else语句,以下是另一种解决方案:
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)
mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]
x, y, z = 0, 1, 3
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]
如果您非常懒惰,可以将值放入数组中。比如
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语句要复杂得多。这就是你试图变得特别懒惰的结果:
还有一件事,你的
if x or y or z == 0:
将编译,但不是按您希望的方式编译。当您在if语句示例中简单地放置一个变量时
if b
程序将检查变量是否为空。写上述陈述的另一种更有意义的方法是
if bool(b)
Bool是python中的一个内置函数,它基本上执行验证布尔语句的命令。如果您不知道布尔语句是什么,那么它就是您现在正在If语句中尝试实现的:
我发现的另一个懒惰的方法是:
if any([x==0, y==0, z==0])
在这里,Set是一种很好的方法,因为它对变量进行排序,这似乎是您的目标。无论参数的顺序如何,{z,y,x}都是{0,1,3}
>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']
这样,整个解决方案都将打开。此代码可能会有所帮助
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;
如Martijn Pieters所述,正确且最快的格式为:
if 1 in {x, y, z}:
使用他的建议,您现在将拥有单独的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循环来清理这个问题:
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])
这里提供的所有优秀答案都集中于原始海报的具体要求,并集中于Martijn Pieters提出的if 1 in{x,y,z}解决方案。 他们忽略了这个问题更广泛的含义: 如何针对多个值测试一个变量? 如果使用字符串,提供的解决方案将不适用于部分命中,例如: 测试系统是否正常工作 tring Wild具有多个值
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
...
>>> 2 in {1, 2, 3}
True
>>> 5 in {1, 2, 3}
False
或
对于这种情况,最容易转换为字符串
>>> [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
但是,应该注意,@codefrester提到,使用这种方法会丢失单词边界,如下所示:
>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
...
True
这3个字母rot在列表中以组合形式存在,但不是作为单个单词存在。测试rot会失败,但如果其中一个列表项在地狱中腐烂,那也会失败。
结果是,如果使用此方法,请小心您的搜索条件,并注意它确实有此限制。单行解决方案:
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)
mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]
x, y, z = 0, 1, 3
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]
或:
您可以使用字典:
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
用Python表示伪代码的最具Python风格的方式是:
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")
看起来你在制造凯撒密码 更普遍的方法是:
input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]
输出
['c', 'd', 'f']
不确定这是否是代码的预期副作用,但输出的顺序将始终被排序
如果这是您想要的,最后一行可以更改为:
sorted([chr(val + origo) for val in inputs])
用一个值测试多个变量:如果{a,b,c}中的1:
用一个变量测试多个值:如果{1,2,3}:中有一个变量:
for value in [var1,var2,var3]:
li.append("targetValue")
您可以尝试下面所示的方法。在此方法中,您可以自由指定/输入希望输入的变量数量
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']
也许你们需要输出位集合的直接公式
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
isc的关系为“c”:
if xyz=0 then isc=1 else isc=0
使用数学公式
[c] :xyz=0和isc=1或xyz=0和isc=1或isc=0和isc=0
[d] :x-1y-1z-1=0和isc=2或xyz=0和isd=2或isc=0和isc=0
通过以下逻辑连接这些公式:
逻辑和是方程的平方和
逻辑或是方程的乘积
你会得到一个总方程式
表示和,你有和的总公式
那么和1是c,和2是d,和4是e,和5是f
在此之后,您可以形成预定义的数组,其中字符串元素的索引将对应于就绪字符串
array[sum]为您提供字符串。这将对您有所帮助
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);
你可以把这个联合起来
x = 0
y = 1
z = 3
在一个变量中
In [1]: xyz = (0,1,3,)
In [2]: mylist = []
将我们的条件更改为:
In [3]: if 0 in xyz:
...: mylist.append("c")
...: if 1 in xyz:
...: mylist.append("d")
...: if 2 in xyz:
...: mylist.append("e")
...: if 3 in xyz:
...: mylist.append("f")
输出:
print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e
In [21]: mylist
Out[21]: ['c', 'd', 'f']
如果没有dict,请尝试以下解决方案:
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)
mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]
x, y, z = 0, 1, 3
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]
并给出:
['c', 'd', 'f']
问题
而用于测试多个值的模式
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
...
>>> 2 in {1, 2, 3}
True
>>> 5 in {1, 2, 3}
False
非常可读,在许多情况下都能工作,但有一个陷阱:
>>> 0 in {True, False}
True
但是我们想要
>>> (0 is True) or (0 is False)
False
解决方案
前面表达式的一个概括基于以下答案:
可以写成
>>> any(0 is item for item in (True, False))
False
虽然此表达式返回正确的结果,但其可读性不如第一个表达式:-您可以通过两种方式对其进行开发
def compareVariables(x,y,z):
mylist = []
if x==0 or y==0 or z==0:
mylist.append('c')
if x==1 or y==1 or z==1:
mylist.append('d')
if x==2 or y==2 or z==2:
mylist.append('e')
if x==3 or y==3 or z==3:
mylist.append('f')
else:
print("wrong input value!")
print('first:',mylist)
compareVariables(1, 3, 2)
或
这里还有一种方法:
x = 0
y = 1
z = 3
mylist = []
if any(i in [0] for i in[x,y,z]):
mylist.append("c")
if any(i in [1] for i in[x,y,z]):
mylist.append("d")
if any(i in [2] for i in[x,y,z]):
mylist.append("e")
if any(i in [3] for i in[x,y,z]):
mylist.append("f")
它是列表理解和任何关键字的混合体。or不是这样工作的,因为
而一般的答案是使用
if 0 in (x, y, z):
...
这不是针对具体问题的最佳方案。在您的情况下,您正在进行重复测试,因此有必要编写一组以下变量:
x = 0
y = 1
z = 3
check_vars = repeat((x, y, z))
values = {x, y, z}
if 0 in values:
mylist.append("c")
if 1 in values:
mylist.append("d")
我们可以使用字典简化此操作-这将产生相同的值:
mappings = {0: "c", 1: "d", ...}
for k in mappings:
if k in values:
mylist.append(mappings[k])
或者,如果mylist的顺序是任意的,则可以在值上循环,并将其与映射匹配:
mappings = {0: "c", 1: "d", ...}
for v in (x, y, z):
if v in mappings:
mylist.append(mappings[v])
我不会那么快就去买固定版本的。元组的创建和迭代非常便宜。至少在我的机器上,只要元组的大小在4-8个元素左右,元组就比集合快。如果你需要扫描更多的内容,可以使用集合,但是如果你想从2-4种可能性中寻找一个项目,那么元组就更快了!如果你能安排最有可能的情况是元组中的第一个,那么赢的机会就更大了:我的测试:timeit.timeit在{seq}.formatseq=tuplerange9,-1中为0-1@dequestarmappartialsetattr:在Python 3.3及更高版本中,集合存储为常量,完全绕过创建时间,消除了创建时间。元组可以便宜地创建,因为Python缓存了一组元组以避免内存流失,这是与集合的最大区别。@DequeStarMapPartialSetttr:如果您只进行成员资格测试,对于整数,集合和元组在理想情况下同样快;匹配第一个元素。在这之后,元组就输给了集合。@MartijnPieters:在这个测试中使用集合文字符号并不能节省成本,除非集合文字的内容也是文字,对吗?如果{x,y,z}:中的1无法缓存该集,因为x,y和z可能会发生变化,因此任何一种解决方案都需要从头构建元组或集合,我怀疑在检查成员资格时可能节省的任何查找开销都会被更大的集合创建时间所淹没。@ShadowRanger:是的,窥视孔优化是否适用于[…]或{…}仅当列表或集合的内容也是不可变的文本时才有效。甚至d=cdef,这导致MyList=[cdef[k]代表[x,y,z]]中的k,或者maplambda i:'cdef'[i],[x,y,z],除了我还不完全习惯的列表理解之外
,我们中的大多数人都有同样的反应:构建那个dict!在dict而不是key的示例中,您将得到错误,因为.append的返回值为None,调用None将给出AttributeError。一般来说,我同意这种方法,但是。dict而不是key是错误的,当字典初始化时,你会得到Mylist=['c','d'],即使你在第一个示例过滤器中注释掉了..loop part也比map好,由于它只返回lambda计算为true的实例,因此理解比lambda的映射简单得多:对于x,y中的v,anyv==0,这并不能回答OP的问题。它只涉及所提供示例中的第一种情况。您应该添加代码完成的内容以及如何完成的描述。仅使用代码的简短回答是不推荐的。如果要以任意/所有方式计算语句列表,则可以使用任意/所有函数。例如:all[1,2,3,4,False]将返回False all[True,1,2,3]将返回True any[False,0,0,False]将返回False any[False,0,True,False]将返回True这个问题是一个非常流行的重复目标,但我认为它不适合这个目的。大多数人会尝试做一些类似于if x==0或1:,这当然与if x或y==0:,但对于新手来说可能有点困惑。考虑到我的x==0或1为什么不能正常工作?对于这些问题,我更愿意将其作为我们的标准复制目标。在与错误值(如0、0.0或False)进行比较时要格外小心。您可以很容易地编写错误的代码,给出正确的答案。相反,请参阅这可能会多次附加相同的代码。Set?这种方法比'if 2 in x,y,z:mylist.append'e'更通用,因为它允许任意比较,例如,如果anyv>=42 in x,y,z:。所有3种方法的性能在{x,y,z},2在x,y,z中,对于_v在x,y,z中的任何_v==2,在CPython3.6中看起来几乎是一样的。参见-1这里有很多不好的实践。列表是Python内置的;改用另一个名称,例如xyz。当你可以做一个,即xyz=[x,y,z]时,为什么你要分四个步骤来构建这个列表?不要使用平行列表,而是使用dict。总而言之,这个解决方案比以前复杂得多。同样对于最后一部分,为什么不做一个理解,即,对于x,y,z中的v,anyv==0?在Python中还有一些其他的东西。@你指的是num_到_字母中的数字吗?默认情况下,您不需要.keys,dict在键上迭代。关于使用字符串,你的意思是这样的,对吗?对于枚举'cdef'中的i,c:如果{x,y,z}中的i:mylist.appendc同意,那将更简单。或者更好的是,s='cdef';mylist=[s[i]代表[x,y,z]@wjandrea是的,你是对的,这是我的错误!我完全忘记了默认行为。不幸的是,我无法编辑我的注释,因此我已将其删除,因为您在注释中突出显示了更好的方法。为什么我在[0]中而不仅仅是I==0?对于像此问题中这样的单个比较,您可以使用==但如果您希望使用多个变量进行多个比较,则可以使用in运算符,如[0,5,4,9,7]中的if anyi对于[x,y,z]中的i