我正在尝试制作一个将多个变量与整数进行比较并输出三个字母的字符串的函数。我想知道是否有办法将其翻译成 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"]
1
any
/all
函数。例如: 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 or 1:
的事情,这当然与 if x or y == 0:
类似,但对于新手来说可能有点困惑。鉴于 “为什么我的 x == 0 or 1
不起作用?” 问题的数量庞大,我更愿意使用 this question 作为这些问题的规范重复目标。
0
、0.0
或 False
等“虚假”值进行比较时要格外小心。您可以轻松编写给出“正确”答案的错误代码。
您误解了布尔表达式的工作原理;它们不像英语句子那样工作,并猜测您在这里谈论的是所有名称的相同比较。您正在寻找:
if x == 1 or y == 1 or z == 1:
x
和 y
单独评估(如果 0
则为 False
,否则为 True
)。
您可以使用针对 a tuple 的包含测试来缩短它:
if 1 in (x, y, z):
或者更好:
if 1 in {x, y, z}:
使用 a set
来利用恒定成本成员资格测试(即 in
无论左侧操作数是什么都需要固定的时间)。
解释
当您使用 or
时,python 将运算符的每一侧视为 separate 表达式。表达式 x or y == 1
首先被视为 x
的布尔测试,然后如果为 False,则测试表达式 y == 1
。
这是由于 operator precedence。 or
运算符的优先级低于 ==
测试,因此对后者进行评估首先。
但是,即使 不是 的情况,并且表达式 x or y or z == 1
实际上被解释为 (x or y or z) == 1
,这仍然不会像您期望的那样做。
x or y or z
将评估为“真实”的第一个参数,例如不是 False
、数字 0 或空(有关 Python 在布尔上下文中认为什么为 false 的详细信息,请参阅 boolean expressions)。
因此对于值 x = 2; y = 1; z = 0
,x or y or z
将解析为 2
,因为这是参数中第一个类似 true 的值。那么 2 == 1
将是 False
,即使 y == 1
将是 True
。
反过来也一样;针对单个变量测试多个值; x == 1 or 2 or 3
会因为同样的原因而失败。使用 x == 1 or x == 2 or x == 3
或 x 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]]
MyList = ["cdef"[k] for k in [x, y, z]]
的 d = "cdef"
map(lambda i: 'cdef'[i], [x, y, z])
正如 Martijn Pieters 所说,正确且最快的格式是:
if 1 in {x, y, z}:
使用他的建议,您现在将拥有单独的 if 语句,以便 Python 将读取每个语句,无论前者是 True
还是 False
。如:
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])
for number in num_to_letters
?您不需要 .keys()
,默认情况下,dicts 会遍历键。关于使用字符串,你的意思是这样的,对吧? for i, c in enumerate('cdef'): if i in {x, y, z}: mylist.append(c)
同意,那会更简单。或者更好的是,s = 'cdef'; mylist = [s[i] for i in [x, y, z]]
写 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
dict
而不是键的示例中,您将收到错误,因为 .append
的返回值为 None
,并且调用 None
会给出 AttributeError
。不过,总的来说,我同意这种方法。
filter
会比 map
更好,因为它只会返回 lambda 计算结果为 true 的实例
any(v == 0 for v 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])
list
是 Python 内置的;请改用其他名称,例如 xyz
。为什么你可以分四步来构建列表,即xyz = [x, y, z]
?不要使用并行列表,而是使用 dict 。总而言之,这个解决方案比 ThatGuyRussell's 复杂得多。同样对于最后一部分,为什么不做一个理解,即any(v == 0 for v in (x, y, z))
? arrays 也是 Python 中的其他内容。
要检查值是否包含在一组变量中,您可以使用内置模块 itertools
和 operator
。
例如:
进口:
from itertools import repeat
from operator import contains
声明变量:
x = 0
y = 1
z = 3
创建值的映射(按照您要检查的顺序):
check_values = (0, 1, 3)
使用 itertools
允许重复变量:
check_vars = repeat((x, y, z))
最后,使用 map
函数创建一个迭代器:
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
ETC...
这比 lambda x: x in (variables)
具有优势,因为 operator
是一个内置模块,并且比使用必须创建自定义就地函数的 lambda
更快、更高效。
检查列表中是否存在非零(或 False)值的另一个选项:
not (x and y and z)
相等的:
not all((x, y, z))
Set 是这里的好方法,因为它对变量进行排序,这似乎是您的目标。无论参数的顺序如何,{z,y,x}
都是 {0,1,3}
。
>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']
这样,整个解决方案是 O(n)。
我认为这会更好地处理它:
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 语句是另一种解决方案:
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)
这里提供的所有优秀答案都集中在原始海报的具体要求上,并集中在 Martijn Pieters 提出的 if 1 in {x,y,z}
解决方案上。
他们忽略的是问题的更广泛含义:
如何针对多个值测试一个变量?
例如,如果使用字符串,则提供的解决方案不适用于部分命中:
测试字符串“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)
...
对于这种情况,最容易转换为字符串
>>> [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
所提到的,这种方法会丢失单词边界,如下所示:
>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
...
True
个字母 rot
确实在列表中组合存在,但不是作为单个单词。测试“ rot ”会失败,但如果列表项之一是“rot in hell”,那也会失败。
结果是,如果使用此方法,请注意您的搜索条件,并注意它确实如此有这个限制。
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;
您可以尝试如下所示的方法。在这种方法中,您可以自由指定/输入您希望输入的变量数量。
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']
一线解决方案:
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 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
如果公式 https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315 使用数学
[c]:(xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))
[d]:((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))
...
通过以下逻辑连接这些公式:
逻辑 和 是方程的平方和
逻辑 or 是方程的乘积
你会有一个总方程表达总和,你有总和的总公式
那么 sum&1 是 c,sum&2 是 d,sum&4 是 e,sum&5 是 f
在此之后,您可以形成预定义的数组,其中字符串元素的索引将对应于准备好的字符串。
array[sum]
为您提供字符串。
在 Python 中表示伪代码的最 Pythonic 方式是:
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")
if any(v >= 42 for v in (x, y, z)):
)。并且所有 3 种方法(2 in {x,y,z}
、2 in (x,y,z)
、any(_v == 2 for _v in (x,y,z))
)的性能在 CPython3.6 中似乎几乎相同(参见 Gist)
它可以很容易地完成
for value in [var1,var2,var3]:
li.append("targetValue")
用一个值测试多个变量:if 1 in {a,b,c}:
用一个变量测试多个值:if a in {1, 2, 3}:
看起来你正在构建某种凯撒密码。
一个更通用的方法是:
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])
您可以使用字典:
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
没有dict,试试这个解决方案:
x, y, z = 0, 1, 3
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]
并给出:
['c', 'd', 'f']
这将对您有所帮助。
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")
输出:
In [21]: mylist
Out[21]: ['c', 'd', 'f']
你可以通过两种方式开发它
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)
或者
def compareVariables(x,y,z):
mylist = []
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')
if 3 in (x,y,z):
mylist.append('f')
else:
print("wrong input value!")
print('second:',mylist)
compareVariables(1, 3, 2)
or
不像 explained by this answer 那样工作。
虽然通用答案将被使用
if 0 in (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
的顺序是任意的,您可以循环遍历 values 并将它们与映射匹配:
mappings = {0: "c", 1: "d", ...}
for v in (x, y, z):
if v in mappings:
mylist.append(mappings[v])
问题
而用于测试多个值的模式
>>> 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
解决方案
前一个表达式的一个概括是基于来自 ytpillai 的答案:
>>> any([0 is True, 0 is False])
False
可以写成
>>> any(0 is item for item in (True, False))
False
虽然这个表达式返回正确的结果,但它不像第一个表达式那样可读:-(
这是另一种方法:
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")
它是列表理解和任何关键字的组合。
i in [0]
而不仅仅是 i == 0
?
没有 if 的用法示例:
x,y,z = 0,1,3
values = {0:"c",1:"d",2:"e",3:"f"} # => as if usage
my_list = [values[i] for i in (x,y,z)]
print(my_list)
首先,对 OR
条件的更正:
你需要说:
if x == 0 or y == 0 or z == 0:
原因是“或”将条件拆分为单独的逻辑部分。你原来的陈述是这样写的,这些部分是:
x
y
z == 0 // or 1, 2, 3 depending on the if statement
最后一部分很好 --- 例如检查 z == 0 --- 但前两部分基本上只是说 if x
和 if y
。由于整数总是计算为 True
,除非它们为 0,这意味着当 x
或 y
不等于 0 时,条件的第一部分总是 True
(在 y 的情况下总是,因为你有 y = 1
,导致你的整个条件(因为 OR
的工作原理)总是 True
。
为避免这种情况,您需要确保条件的所有部分(OR
的每一侧)本身都有意义(您可以通过假装 OR
语句的另一侧没有'来做到这一点' t 存在)。这样您就可以确认您的 OR
条件是否定义正确。
您可以像这样单独编写语句:
if x == 0
if y == 0
if z == 0
这意味着与 OR
关键字的正确合并是:
if x == 0 or y == 0 or z == 0
二、如何解决问题:
您基本上是想检查是否有任何变量与给定整数匹配,如果是,则在一对一映射中为其分配一个匹配的字母。您想对某个整数列表执行此操作,以便输出是字母列表。你会这样做:
def func(x, y, z):
result = []
for integer, letter in zip([0, 1, 2, 3], ['c', 'd', 'e', 'f']):
if x == integer or y == integer or z == integer:
result.append(letter)
return result
同样,您可以使用 LIST COMPRHENSION 更快地获得相同的结果:
def func(x, y, z):
return [
letter
for integer, letter in zip([0, 1, 2, 3], ['c', 'd', 'e', 'f'])
if x == integer or y == integer or z == integer
]
#selection
: a=np.array([0,1,3])
#options
: np.diag(['c','d','e','f'])
array([['c', '', '', ''],
['', 'd', '', ''],
['', '', 'e', ''],
['', '', '', 'f']], dtype='<U1')
现在我们可以使用 as [row,col] 选择器,它的作用就像 any(...) 条件:
#list of options[sel,sel]
: np.diag(['c','d','e','f'])[a,a]
array(['c', 'd', 'f'], dtype='<U1')
set
版本。元组的创建和迭代非常便宜。至少在我的机器上,只要元组的大小在 4-8 个元素左右,元组就比集合快。如果您必须扫描更多,请使用集合,但如果您正在寻找 2-4 种可能性中的项目,则元组仍然更快!如果您可以将最有可能的情况安排在元组中,则胜利更大:(我的测试:timeit.timeit('0 in {seq}'.format(seq=tuple(range(9, -1, -1))))
)set
文字的内容也是文字,否则在此测试中使用set
文字表示法并不是一种节省,对吧?if 1 in {x, y, z}:
无法缓存set
,因为x
、y
和z
可能会发生变化,因此任一解决方案都需要从头开始构建tuple
或set
,我怀疑任何查找节省在检查成员资格时,您可能会遇到更多的set
创建时间。in [...]
或in {...}
)仅在列表或集合的内容也是不可变文字时才有效。