标签归档:boolean-logic

熊猫:索引数据框时出现多种情况-意外行为

问题:熊猫:索引数据框时出现多种情况-意外行为

我正在按两列中的值过滤数据框中的行。

出于某种原因,OR运算符的行为类似于我期望AND运算符的行为,反之亦然。

我的测试代码:

import pandas as pd

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',])

结果:

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

如您所见,AND运算符将删除其中至少一个等于的每一行-1。另一方面,OR运算符要求两个值相等-1才能删除它们。我期望结果恰好相反。任何人都可以解释这种行为吗?

我正在使用熊猫0.13.1。

I am filtering rows in a dataframe by values in two columns.

For some reason the OR operator behaves like I would expect AND operator to behave and vice versa.

My test code:

import pandas as pd

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',])

And the result:

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

As you can see, the AND operator drops every row in which at least one value equals -1. On the other hand, the OR operator requires both values to be equal to -1 to drop them. I would expect exactly the opposite result. Could anyone explain this behavior, please?

I am using pandas 0.13.1.


回答 0

如您所见,AND运算符会删除每一行中至少有一个等于-1的值。另一方面,OR运算符要求两个值都等于-1才能删除它们。

那就对了。请记住,您是根据要保留的内容而不是要丢弃的内容来写条件。对于df1

df1 = df[(df.a != -1) & (df.b != -1)]

您说的是“保留其中df.a不是-1且df.b不是-1的行”,这与删除其中至少一个值为-1的每一行相同。

对于df2

df2 = df[(df.a != -1) | (df.b != -1)]

您说的是“保留其中任一行df.adf.b都不为-1的行”,这与删除两个值均为-1的行相同。

PS:连锁访问会给df['a'][1] = -1您带来麻烦。最好养成使用.loc和的习惯.iloc

As you can see, the AND operator drops every row in which at least one value equals -1. On the other hand, the OR operator requires both values to be equal to -1 to drop them.

That’s right. Remember that you’re writing the condition in terms of what you want to keep, not in terms of what you want to drop. For df1:

df1 = df[(df.a != -1) & (df.b != -1)]

You’re saying “keep the rows in which df.a isn’t -1 and df.b isn’t -1″, which is the same as dropping every row in which at least one value is -1.

For df2:

df2 = df[(df.a != -1) | (df.b != -1)]

You’re saying “keep the rows in which either df.a or df.b is not -1″, which is the same as dropping rows where both values are -1.

PS: chained access like df['a'][1] = -1 can get you into trouble. It’s better to get into the habit of using .loc and .iloc.


回答 1

您可以使用query(),即:

df_filtered = df.query('a == 4 & b != 2')

You can use query(), i.e.:

df_filtered = df.query('a == 4 & b != 2')

回答 2

这里有一些数学逻辑理论

“ NOT a AND NOT b”“ NOT(a OR b)”相同,因此:

“ a NOT -1 AND b NOT -1” 等同于 “ NOT(a为-1 OR b为-1)”,与“(a is -1 OR b为-1)”的(补数)相反。

因此,如果您想要完全相反的结果,则df1和df2应如下所示:

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]

A little mathematical logic theory here:

“NOT a AND NOT b” is the same as “NOT (a OR b)”, so:

“a NOT -1 AND b NOT -1” is equivalent of “NOT (a is -1 OR b is -1)”, which is opposite (Complement) of “(a is -1 OR b is -1)”.

So if you want exact opposite result, df1 and df2 should be as below:

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]

有没有更优雅的表达方式((x == a和y == b)或(x == b和y == a))?

问题:有没有更优雅的表达方式((x == a和y == b)或(x == b和y == a))?

我正在尝试使用((x == a and y == b) or (x == b and y == a))Python 进行评估,但似乎有些冗长。有没有更优雅的方式?

I’m trying to evaluate ((x == a and y == b) or (x == b and y == a)) in Python, but it seems a bit verbose. Is there a more elegant way?


回答 0

如果元素是可哈希的,则可以使用集合:

{a, b} == {y, x}

If the elements are hashable, you could use sets:

{a, b} == {y, x}

回答 1

我认为最好的办法是将它们包装到元组中:

if (a, b) == (x, y) or (a, b) == (y, x)

或者,也许将其包装在集合中

if (a, b) in {(x, y), (y, x)}

正因为有几条评论提到了它,所以我做了一些计时,当查找失败时,元组和集合在这里的表现相同:

from timeit import timeit

x = 1
y = 2
a = 3
b = 4

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
32.8357742

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
31.6169182

尽管查找成功时元组实际上更快:

x = 1
y = 2
a = 1
b = 2

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
35.6219458

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
27.753138700000008

我选择使用集合是因为​​我正在执行成员资格查找,并且从概念上讲,集合比该元组更适合该用例。如果您在特定用例中测量了两种结构之间的显着差异,请选择速度较快的一种。我认为性能并不是这里的因素。

I think the best you could get is to package them into tuples:

if (a, b) == (x, y) or (a, b) == (y, x)

Or, maybe wrap that in a set lookup

if (a, b) in {(x, y), (y, x)}

Just since it was mentioned by a couple comments, I did some timings, and tuples and sets appear to perform identically here when the lookup fails:

from timeit import timeit

x = 1
y = 2
a = 3
b = 4

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
32.8357742

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
31.6169182

Although tuples are actually faster when the lookup succeeds:

x = 1
y = 2
a = 1
b = 2

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
35.6219458

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
27.753138700000008

I chose to use a set because I’m doing a membership lookup, and conceptually a set is a better fit for that use-case than a tuple. If you measured a significant different between the two structures in a particular use case, go with the faster one. I don’t think performance is a factor here though.


回答 2

元组使其更具可读性:

(x, y) == (a, b) or (x, y) == (b, a)

这提供了一个线索:我们正在检查序列x, y是否等于序列,a, b但忽略了排序。那就是设置平等!

{x, y} == {a, b}

Tuples make it slightly more readable:

(x, y) == (a, b) or (x, y) == (b, a)

This gives a clue: we’re checking whether the sequence x, y is equal to the sequence a, b but ignoring ordering. That’s just set equality!

{x, y} == {a, b}

回答 3

如果项目不可散列,但支持排序比较,则可以尝试:

sorted((x, y)) == sorted((a, b))

If the items aren’t hashable, but support ordering comparisons, you could try:

sorted((x, y)) == sorted((a, b))

回答 4

我认为,最优雅的方式是

(x, y) in ((a, b), (b, a))

这比使用集(即{a, b} == {y, x}其他答案中指出的集)更好的方法,因为我们不需要考虑变量是否可哈希。

The most elegant way, in my opinion, would be

(x, y) in ((a, b), (b, a))

This is a better way than using sets, i.e. {a, b} == {y, x}, as indicated in other answers because we don’t need to think if the variables are hashable.


回答 5

如果这些是数字,则可以使用(x+y)==(a+b) and (x*y)==(a*b)

如果这些是可比较的项目,则可以使用min(x,y)==min(a,b) and max(x,y)==max(a,b)

但是((x == a and y == b) or (x == b and y == a))很清楚,安全并且更笼统。

If these are numbers, you can use (x+y)==(a+b) and (x*y)==(a*b).

If these are comparable items, you can use min(x,y)==min(a,b) and max(x,y)==max(a,b).

But ((x == a and y == b) or (x == b and y == a)) is clear, safe, and more general.


回答 6

作为对两个以上变量的概括,我们可以使用itertools.permutations。那不是

(x == a and y == b and z == c) or (x == a and y == c and z == b) or ...

我们可以写

(x, y, z) in itertools.permutations([a, b, c])

当然还有两个变量版本:

(x, y) in itertools.permutations([a, b])

As a generalization to more than two variables we can use itertools.permutations. That is instead of

(x == a and y == b and z == c) or (x == a and y == c and z == b) or ...

we can write

(x, y, z) in itertools.permutations([a, b, c])

And of course the two variable version:

(x, y) in itertools.permutations([a, b])

回答 7

您可以使用元组表示数据,然后检查是否包含集合,例如:

def test_fun(x, y):
    test_set = {(a, b), (b, a)}

    return (x, y) in test_set

You can use tuples to represent your data and then check for set inclusion, like:

def test_fun(x, y):
    test_set = {(a, b), (b, a)}

    return (x, y) in test_set

回答 8

您已经获得了最具可读性的解决方案。还有其他表达方式,也许用更少的字符,但是阅读起来却不那么直接。

根据值实际代表最好的选择的方式,是将支票包装在一个具有语音名称的函数中。替代地或另外,您可以在专用的高级类对象中分别对对象x,y和a,b建模,然后可以在类相等性检查方法或专用的自定义函数中将其与比较逻辑进行比较。

You already got the most readable solution. There are other ways to express this, perhaps with less characters, but they are less straight-forward to read.

Depending on what the values actually represent your best bet is to wrap the check in a function with a speaking name. Alternatively or in addition, you can model the objects x,y and a,b each in dedicated higher class objects that you then can compare with the logic of the comparison in a class equality check method or a dedicated custom function.


回答 9

看来,OP仅关注两个变量的情况,但是由于StackOverflow也适用于以后搜索相同问题的人员,因此,我将在此处尝试更详细地讨论这种情况。先前的一个答案已经包含了使用的通用答案itertools.permutations(),但是该方法可以O(N*N!)进行比较,因为每个项都有N!排列N。(这是此答案的主要动机)

首先,让我们总结一下先前答案中的某些方法如何应用于一般情况,以此作为本文介绍方法的动力。我将使用A来引用(x, y)B引用(a, b),它们可以是任意(但相等)长度的元组。

set(A) == set(B)速度很快,但是仅在值是可哈希的并且可以保证元组之一不包含任何重复值的情况下才起作用。(例如{1, 1, 2} == {1, 2, 2},@ user2357112在@Daniel Mesejo的回答下指出)

通过使用带计数的字典(而不是集合),可以将先前的方法扩展为使用重复值,而不是使用集合:(这仍然有一个局限性,即所有值都必须是可哈希的,因此,可变值之类的方法list将不起作用)

def counts(items):
    d = {}
    for item in items:
        d[item] = d.get(item, 0) + 1
    return d

counts(A) == counts(B)

sorted(A) == sorted(B)不需要可散列的值,但速度稍慢,而是需要可排序的值。(因此例如complex将无法工作)

A in itertools.permutations(B)不需要哈希值或可排序的值,但是正如已经提到的,它具有O(N*N!)复杂性,因此即使只有11个项目,也可能需要一秒钟的时间才能完成。

因此,有没有一种方法可以像一般方法那样,但是会更快吗?为什么是,通过“手动”检查每个项目的数量是否相同:(此项目的复杂度为O(N^2),因此这对于大输入也不是一件好事;在我的机器上,一万个项目可能要花一秒钟的时间,但是较小的输入(例如10个项目,这与其他项目一样快)

def unordered_eq(A, B):
    for a in A:
        if A.count(a) != B.count(a):
            return False
    return True

为了获得最佳的性能,人们可能会想尝试的dict第一个基于方法,回落到sorted基于方法如果失败了,由于unhashable值,最后回落到count基方法,如果太因unorderable值失败。

It seems the OP was only concerned with the case of two variables, but since StackOverflow is also for those who search for the same question later, I’ll try to tackle the generic case here in some detail; One previous answer already contains a generic answer using itertools.permutations(), but that method leads to O(N*N!) comparisons, since there are N! permutations with N items each. (This was the main motivation for this answer)

First, let’s summarize how some of the methods in previous answers apply to the generic case, as motivation for the method presented here. I’ll be using A to refer to (x, y) and B to refer to (a, b), which can be tuples of arbitrary (but equal) length.

set(A) == set(B) is fast, but only works if the values are hashable and you can guarantee that one of the tuples doesn’t contain any duplicate values. (Eg. {1, 1, 2} == {1, 2, 2}, as pointed out by @user2357112 under @Daniel Mesejo’s answer)

The previous method can be extended to work with duplicate values by using dictionaries with counts, instead of sets: (This still has the limitation that all values need to be hashable, so eg. mutable values like list won’t work)

def counts(items):
    d = {}
    for item in items:
        d[item] = d.get(item, 0) + 1
    return d

counts(A) == counts(B)

sorted(A) == sorted(B) doesn’t require hashable values, but is slightly slower, and requires orderable values instead. (So eg. complex won’t work)

A in itertools.permutations(B) doesn’t require hashable or orderable values, but like already mentioned, it has O(N*N!) complexity, so even with just 11 items, it can take over a second to finish.

So, is there a way to be as general, but do it considerably faster? Why yes, by “manually” checking that there’s the same amount of each item: (The complexity of this one is O(N^2), so this isn’t good for large inputs either; On my machine, 10k items can take over a second – but with smaller inputs, like 10 items, this is just as fast as the others)

def unordered_eq(A, B):
    for a in A:
        if A.count(a) != B.count(a):
            return False
    return True

To get the best performance, one might want to try the dict-based method first, fall back to the sorted-based method if that fails due to unhashable values, and finally fall back to the count-based method if that too fails due to unorderable values.


如何获得熊猫系列的按元素逻辑非?

问题:如何获得熊猫系列的按元素逻辑非?

我有一个Series包含布尔值的pandas 对象。如何获得包含NOT每个值逻辑的序列?

例如,考虑一个包含以下内容的系列:

True
True
True
False

我想要获得的系列将包含:

False
False
False
True

这似乎应该相当简单,但是显然我放错了我的mojo =(

I have a pandas Series object containing boolean values. How can I get a series containing the logical NOT of each value?

For example, consider a series containing:

True
True
True
False

The series I’d like to get would contain:

False
False
False
True

This seems like it should be reasonably simple, but apparently I’ve misplaced my mojo =(


回答 0

要反转布尔系列,请使用~s

In [7]: s = pd.Series([True, True, False, True])

In [8]: ~s
Out[8]: 
0    False
1    False
2     True
3    False
dtype: bool

使用Python2.7,NumPy 1.8.0,Pandas 0.13.1:

In [119]: s = pd.Series([True, True, False, True]*10000)

In [10]:  %timeit np.invert(s)
10000 loops, best of 3: 91.8 µs per loop

In [11]: %timeit ~s
10000 loops, best of 3: 73.5 µs per loop

In [12]: %timeit (-s)
10000 loops, best of 3: 73.5 µs per loop

从Pandas 0.13.0开始,Series不再是numpy.ndarray;的子类。它们现在是的子类pd.NDFrame。这可能与为什么np.invert(s)不再像~s或一样快有关-s

注意:timeit结果可能取决于许多因素,包括硬件,编译器,操作系统,Python,NumPy和Pandas版本。

To invert a boolean Series, use ~s:

In [7]: s = pd.Series([True, True, False, True])

In [8]: ~s
Out[8]: 
0    False
1    False
2     True
3    False
dtype: bool

Using Python2.7, NumPy 1.8.0, Pandas 0.13.1:

In [119]: s = pd.Series([True, True, False, True]*10000)

In [10]:  %timeit np.invert(s)
10000 loops, best of 3: 91.8 µs per loop

In [11]: %timeit ~s
10000 loops, best of 3: 73.5 µs per loop

In [12]: %timeit (-s)
10000 loops, best of 3: 73.5 µs per loop

As of Pandas 0.13.0, Series are no longer subclasses of numpy.ndarray; they are now subclasses of pd.NDFrame. This might have something to do with why np.invert(s) is no longer as fast as ~s or -s.

Caveat: timeit results may vary depending on many factors including hardware, compiler, OS, Python, NumPy and Pandas versions.


回答 1

@unutbu的答案是正确的,只是想添加一个警告,说明您的蒙版必须是dtype bool,而不是’object’。也就是说,您的面具永远都不会有。看到这里 -即使您的面具现在是不含纳米的,它仍将是“对象”类型。

“对象”系列的逆函数不会引发错误,相反,您将获得整数的垃圾掩码,这些掩码将无法按预期工作。

In[1]: df = pd.DataFrame({'A':[True, False, np.nan], 'B':[True, False, True]})
In[2]: df.dropna(inplace=True)
In[3]: df['A']
Out[3]:
0    True
1   False
Name: A, dtype object
In[4]: ~df['A']
Out[4]:
0   -2
0   -1
Name: A, dtype object

与同事讨论了这个问题之后,我得到了一个解释:看起来熊猫正在恢复按位运算符:

In [1]: ~True
Out[1]: -2

正如@geher所说,您可以先将其转换为具有astype的bool,然后再使用〜逆

~df['A'].astype(bool)
0    False
1     True
Name: A, dtype: bool
(~df['A']).astype(bool)
0    True
1    True
Name: A, dtype: bool

@unutbu’s answer is spot on, just wanted to add a warning that your mask needs to be dtype bool, not ‘object’. Ie your mask can’t have ever had any nan’s. See here – even if your mask is nan-free now, it will remain ‘object’ type.

The inverse of an ‘object’ series won’t throw an error, instead you’ll get a garbage mask of ints that won’t work as you expect.

In[1]: df = pd.DataFrame({'A':[True, False, np.nan], 'B':[True, False, True]})
In[2]: df.dropna(inplace=True)
In[3]: df['A']
Out[3]:
0    True
1   False
Name: A, dtype object
In[4]: ~df['A']
Out[4]:
0   -2
0   -1
Name: A, dtype object

After speaking with colleagues about this one I have an explanation: It looks like pandas is reverting to the bitwise operator:

In [1]: ~True
Out[1]: -2

As @geher says, you can convert it to bool with astype before you inverse with ~

~df['A'].astype(bool)
0    False
1     True
Name: A, dtype: bool
(~df['A']).astype(bool)
0    True
1    True
Name: A, dtype: bool

回答 2

我只是试一试:

In [9]: s = Series([True, True, True, False])

In [10]: s
Out[10]: 
0     True
1     True
2     True
3    False

In [11]: -s
Out[11]: 
0    False
1    False
2    False
3     True

I just give it a shot:

In [9]: s = Series([True, True, True, False])

In [10]: s
Out[10]: 
0     True
1     True
2     True
3    False

In [11]: -s
Out[11]: 
0    False
1    False
2    False
3     True

回答 3

您也可以使用numpy.invert

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: s = pd.Series([True, True, False, True])

In [4]: np.invert(s)
Out[4]: 
0    False
1    False
2     True
3    False

编辑:性能差异出现在Ubuntu 12.04,Python 2.7,NumPy 1.7.0上-尽管使用NumPy 1.6.2似乎不存在:

In [5]: %timeit (-s)
10000 loops, best of 3: 26.8 us per loop

In [6]: %timeit np.invert(s)
100000 loops, best of 3: 7.85 us per loop

In [7]: %timeit ~s
10000 loops, best of 3: 27.3 us per loop

You can also use numpy.invert:

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: s = pd.Series([True, True, False, True])

In [4]: np.invert(s)
Out[4]: 
0    False
1    False
2     True
3    False

EDIT: The difference in performance appears on Ubuntu 12.04, Python 2.7, NumPy 1.7.0 – doesn’t seem to exist using NumPy 1.6.2 though:

In [5]: %timeit (-s)
10000 loops, best of 3: 26.8 us per loop

In [6]: %timeit np.invert(s)
100000 loops, best of 3: 7.85 us per loop

In [7]: %timeit ~s
10000 loops, best of 3: 27.3 us per loop

回答 4

NumPy较慢,因为它将输入强制转换为布尔值(因此None和0变为False,其他所有值变为True)。

import pandas as pd
import numpy as np
s = pd.Series([True, None, False, True])
np.logical_not(s)

给你

0    False
1     True
2     True
3    False
dtype: object

而〜s会崩溃。在大多数情况下,与NumPy相比,波浪号是一个更安全的选择。

熊猫0.25,小米1.17

NumPy is slower because it casts the input to boolean values (so None and 0 becomes False and everything else becomes True).

import pandas as pd
import numpy as np
s = pd.Series([True, None, False, True])
np.logical_not(s)

gives you

0    False
1     True
2     True
3    False
dtype: object

whereas ~s would crash. In most cases tilde would be a safer choice than NumPy.

Pandas 0.25, NumPy 1.17


Python是否支持短路?

问题:Python是否支持短路?

Python是否支持布尔表达式中的短路?

Does Python support short-circuiting in boolean expressions?


回答 0

是的andor操作员都短路了-请参阅docs

Yep, both and and or operators short-circuit — see the docs.


回答 1

捷径,运营商andor

我们首先定义一个有用的函数来确定是否执行了某些操作。一个简单的函数,它接受一个参数,输出一条消息并返回输入,且未更改。

>>> def fun(i):
...     print "executed"
...     return i
... 

在以下示例中,可以观察到Python的捷径andor

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

注意:解释器认为以下值表示false:

        False    None    0    ""    ()    []     {}

功能中的捷径:any()all()

Python any()all()函数还支持短路。如文档所示;他们按顺序评估序列中的每个元素,直到找到可以提前退出评估的结果。考虑下面的示例以了解两者。

该函数any()检查是否有任何元素为True。一旦遇到True,它将立即停止执行并返回True。

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

该函数all()检查所有元素是否为True,并在遇到False时立即停止执行:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

链式比较中的捷径:

此外,在Python中

比较可以任意链接 ; 例如,x < y <= z与等效x < y and y <= z,除了y只被评估一次(但是在两种情况下z,如果x < y发现为假,则根本不评估)。

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

编辑:
需要注意的另一点要点:-逻辑andor Python中的运算符返回操作数的值,而不是布尔值(TrueFalse)。例如:

操作x and y给出结果if x is false, then x, else y

不像在其他语言,例如&&||在C运算该返回0或1。

例子:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

同样,or运算符返回最左边的值,其中bool(value)==,True否则返回最右边的假值(根据捷径),例如:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

那么,这有什么用呢?Magnus Lie Hetland 在《实用Python》中给出的一个示例用法:
假设用户应该输入他或她的名字,但是可以选择不输入任何东西,在这种情况下,您想使用默认值'<unknown>'。您可以使用if语句,但也可以非常简洁地陈述一下:

In [171]: name = raw_input('Enter Name: ') or '<Unkown>'
Enter Name: 

In [172]: name
Out[172]: '<Unkown>'

换句话说,如果raw_input的返回值是true(不是一个空字符串),则将其分配给name(不变);否则,它将返回true。否则,默认设置'<unknown>'name

Short-circuiting behavior in operator and, or:

Let’s first define a useful function to determine if something is executed or not. A simple function that accepts an argument, prints a message and returns the input, unchanged.

>>> def fun(i):
...     print "executed"
...     return i
... 

One can observe the Python’s short-circuiting behavior of and, or operators in the following example:

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

Note: The following values are considered by the interpreter to mean false:

        False    None    0    ""    ()    []     {}

Short-circuiting behavior in function: any(), all():

Python’s any() and all() functions also support short-circuiting. As shown in the docs; they evaluate each element of a sequence in-order, until finding a result that allows an early exit in the evaluation. Consider examples below to understand both.

The function any() checks if any element is True. It stops executing as soon as a True is encountered and returns True.

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

The function all() checks all elements are True and stops executing as soon as a False is encountered:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

Short-circuiting behavior in Chained Comparison:

Additionally, in Python

Comparisons can be chained arbitrarily; for example, x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

Edit:
One more interesting point to note :- Logical and, or operators in Python returns an operand’s value instead of a Boolean (True or False). For example:

Operation x and y gives the result if x is false, then x, else y

Unlike in other languages e.g. &&, || operators in C that return either 0 or 1.

Examples:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

Similarly or operator return left most value for which bool(value) == True else right most false value (according to short-circuiting behavior), examples:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

So, how is this useful? One example use given in Practical Python By Magnus Lie Hetland:
Let’s say a user is supposed to enter his or her name, but may opt to enter nothing, in which case you want to use the default value '<unknown>'. You could use an if statement, but you could also state things very succinctly:

In [171]: name = raw_input('Enter Name: ') or '<Unkown>'
Enter Name: 

In [172]: name
Out[172]: '<Unkown>'

In other words, if the return value from raw_input is true (not an empty string), it is assigned to name (nothing changes); otherwise, the default '<unknown>' is assigned to name.


回答 2

是。在python解释器中尝试以下操作:

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

要么

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero

Yes. Try the following in your python interpreter:

and

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

or

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero

如何针对一个值测试多个变量?

问题:如何针对一个值测试多个变量?

我正在尝试制作一个将多个变量与一个整数进行比较并输出三个字母的字符串的函数。我想知道是否有一种方法可以将其转换为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"]

这样的事情可能吗?

I’m trying to make a function that will compare multiple variables to an integer and output a string of three letters. I was wondering if there was a way to translate this into Python. So say:

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")

which would return a list of:

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

Is something like this possible?


回答 0

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

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

xy以其他方式自行评估(False如果为0,则为True)。

您可以使用针对元组的容纳测试来缩短该时间:

if 1 in (x, y, z):

还是更好:

if 1 in {x, y, z}:

使用aset来利用固定成本的成员资格测试(in无论左侧操作数是多少,都花费固定的时间)。

使用时or,python会将运算符的每一面视为单独的表达式。该表达式x or y == 1首先被视为的布尔测试x,然后如果为False,y == 1则测试该表达式。

这是由于运算符的优先级。的or操作者具有较低的优先级比所述==测试,所以后者被评估第一

但是,即使不是这种情况,并且x or y or z == 1实际上该表达式被解释为(x or y or z) == 1,该表达式仍不会执行您期望的操作。

x or y or z会求值为第一个“真实的”参数,例如,不是False,数字0或为空(有关布尔值在Python上下文中认为Python为假的详细信息,请参见布尔值表达式)。

因此,对于values x = 2; y = 1; z = 0x or y or z将解析为2,因为那是参数中的第一个真值。然后2 == 1False,即使y == 1True

反之亦然;针对单个变量测试多个值;x == 1 or 2 or 3会因为相同的原因而失败。使用x == 1 or x == 2 or x == 3x in {1, 2, 3}

You misunderstand how boolean expressions work; they don’t work like an English sentence and guess that you are talking about the same comparison for all names here. You are looking for:

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

x and y are otherwise evaluated on their own (False if 0, True otherwise).

You can shorten that using a containment test against a tuple:

if 1 in (x, y, z):

or better still:

if 1 in {x, y, z}:

using a set to take advantage of the constant-cost membership test (in takes a fixed amount of time whatever the left-hand operand is).

When you use or, python sees each side of the operator as separate expressions. The expression x or y == 1 is treated as first a boolean test for x, then if that is False, the expression y == 1 is tested.

This is due to operator precedence. The or operator has a lower precedence than the == test, so the latter is evaluated first.

However, even if this were not the case, and the expression x or y or z == 1 was actually interpreted as (x or y or z) == 1 instead, this would still not do what you expect it to do.

x or y or z would evaluate to the first argument that is ‘truthy’, e.g. not False, numeric 0 or empty (see boolean expressions for details on what Python considers false in a boolean context).

So for the values x = 2; y = 1; z = 0, x or y or z would resolve to 2, because that is the first true-like value in the arguments. Then 2 == 1 would be False, even though y == 1 would be True.

The same would apply to the inverse; testing multiple values against a single variable; x == 1 or 2 or 3 would fail for the same reasons. Use x == 1 or x == 2 or x == 3 or x in {1, 2, 3}.


回答 1

使用以下字典结构可以更轻松地解决您的问题:

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

Your problem is more easily addressed with a dictionary structure like:

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

回答 2

正如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])

As stated by Martijn Pieters, the correct, and fastest, format is:

if 1 in {x, y, z}:

Using his advice you would now have separate if-statements so that Python will read each statement whether the former were True or False. Such as:

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")
...

This will work, but if you are comfortable using dictionaries (see what I did there), you can clean this up by making an initial dictionary mapping the numbers to the letters you want, then just using a for-loop:

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])

回答 3

直接的写法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)

BTW很多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

The direct way to write x or y or z == 0 is

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

But I dont think, you like it. :) And this way is ugly.

The other way (a better) is:

0 in (x, y, z)

BTW lots of ifs could be written as something like this

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

回答 4

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

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

程序将检查变量是否不为null。编写以上语句的另一种方法(更有意义)是

if bool(b)

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

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

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

If you ARE very very lazy, you can put the values inside an array. Such as

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

You can also put the numbers and letters in a dictionary and do it, but this is probably a LOT more complicated than simply if statements. That’s what you get for trying to be extra lazy :)

One more thing, your

if x or y or z == 0:

will compile, but not in the way you want it to. When you simply put a variable in an if statement (example)

if b

the program will check if the variable is not null. Another way to write the above statement (which makes more sense) is

if bool(b)

Bool is an inbuilt function in python which basically does the command of verifying a boolean statement (If you don’t know what that is, it is what you are trying to make in your if statement right now :))

Another lazy way I found is :

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

回答 5

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

例如:

进口:

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

等等…

这是一个优势,lambda x: x in (variables)因为operator它是内置模块,并且比必须使用lambda它来创建自定义就地功能的模块更快,更高效。

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

not (x and y and z)

当量:

not all((x, y, z))

To check if a value is contained within a set of variables you can use the inbuilt modules itertools and operator.

For example:

Imports:

from itertools import repeat
from operator import contains

Declare variables:

x = 0
y = 1
z = 3

Create mapping of values (in the order you want to check):

check_values = (0, 1, 3)

Use itertools to allow repetition of the variables:

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

Finally, use the map function to create an iterator:

checker = map(contains, check_vars, check_values)

Then, when checking for the values (in the original order), use next():

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

etc…

This has an advantage over the lambda x: x in (variables) because operator is an inbuilt module and is faster and more efficient than using lambda which has to create a custom in-place function.

Another option for checking if there is a non-zero (or False) value in a list:

not (x and y and z)

Equivalent:

not all((x, y, z))

回答 6

设置是这里的好方法,因为它对变量进行排序,这似乎是您的目标。{z,y,x}{0,1,3}参数的任何命令。

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

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

Set is the good approach here, because it orders the variables, what seems to be your goal here. {z,y,x} is {0,1,3} whatever the order of the parameters.

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

This way, the whole solution is O(n).


回答 7

这里提供的所有出色答案都集中在原始海报的特定要求上,并集中在if 1 in {x,y,z}Martijn Pieters提出的解决方案上。
他们忽略了这个问题的更广泛含义:
如何针对多个值测试一个变量?
如果使用例如字符串,则提供的解决方案不适用于部分匹配:
测试字符串“ 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

这3个字母rot确实存在于列表中,但不是单个单词。测试“腐烂”将失败,但是如果列表项之一“在地狱腐烂”,那也将失败。
结果是,如果使用此方法,请注意您的搜索条件,并注意它确实有此限制。

All of the excellent answers provided here concentrate on the specific requirement of the original poster and concentrate on the if 1 in {x,y,z} solution put forward by Martijn Pieters.
What they ignore is the broader implication of the question:
How do I test one variable against multiple values?
The solution provided will not work for partial hits if using strings for example:
Test if the string “Wild” is in multiple values

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

or

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

for this scenario it’s easiest to convert to a 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

It should be noted however, as mentioned by @codeforester, that word boundries are lost with this method, as in:

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

the 3 letters rot do exist in combination in the list but not as an individual word. Testing for ” rot ” would fail but if one of the list items were “rot in hell”, that would fail as well.
The upshot being, be careful with your search criteria if using this method and be aware that it does have this limitation.


回答 8

我认为这样会更好地处理它:

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

I think this will handle it better:

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]

Output:

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

回答 9

如果要使用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)

If you want to use if, else statements following is another solution:

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)

回答 10

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]
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]

回答 11

此代码可能会有所帮助

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;

This code may be helpful

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;

回答 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']

You can try the method shown below. In this method, you will have the freedom to specify/input the number of variables that you wish to enter.

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']

回答 13

一线解决方案:

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)]

One line solution:

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

Or:

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

回答 14

也许您需要直接的公式来设置输出位。

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))

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

  • 逻辑and是方程的平方和
  • 逻辑or是方程式的产物

你会有一个总和表示总和,你总和公式

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

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

array[sum] 给你字符串。

Maybe you need direct formula for output bits set.

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

Let’s map to bits: 'c':1 'd':0xb10 'e':0xb100 'f':0xb1000

Relation of isc (is ‘c’):

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

Use math if formula 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))

Connect these formulas by following logic:

  • logic and is the sum of squares of equations
  • logic or is the product of equations

and you’ll have a total equation express sum and you have total formula of sum

then sum&1 is c, sum&2 is d, sum&4 is e, sum&5 is f

After this you may form predefined array where index of string elements would correspond to ready string.

array[sum] gives you the string.


回答 15

它可以很容易地完成

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

It can be done easily as

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

回答 16

用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")

The most mnemonic way of representing your pseudo-code in Python would be:

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")

回答 17

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

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

To test multiple variables with one single value: if 1 in {a,b,c}:

To test multiple values with one variable: if a in {1, 2, 3}:


回答 18

看起来您正在构建某种凯撒密码。

更为通用的方法是:

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])

Looks like you’re building some kind of Caesar cipher.

A much more generalized approach is this:

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

outputs

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

Not sure if it’s a desired side effect of your code, but the order of your output will always be sorted.

If this is what you want, the final line can be changed to:

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

回答 19

您可以使用字典:

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

You can use dictionary :

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

回答 20

如果没有字典,请尝试以下解决方案:

x, y, z = 0, 1, 3    
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]

并给出:

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

Without dict, try this solution:

x, y, z = 0, 1, 3    
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]

and gives:

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

回答 21

这将为您提供帮助。

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);

This will help you.

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);

回答 22

你可以团结起来

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']

You can unite this

x = 0
y = 1
z = 3

in one variable.

In [1]: xyz = (0,1,3,) 
In [2]: mylist = []

Change our conditions as:

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") 

Output:

In [21]: mylist                                                                                
Out[21]: ['c', 'd', 'f']

回答 23

问题

同时测试多个值的模式

>>> 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

虽然此表达式返回正确的结果,但它不如第一个表达式可读:

Problem

While the pattern for testing multiple values

>>> 2 in {1, 2, 3}
True
>>> 5 in {1, 2, 3}
False

is very readable and is working in many situation, there is one pitfall:

>>> 0 in {True, False}
True

But we want to have

>>> (0 is True) or (0 is False)
False

Solution

One generalization of the previous expression is based on the answer from ytpillai:

>>> any([0 is True, 0 is False])
False

which can be written as

>>> any(0 is item for item in (True, False))
False

While this expression returns the right result it is not as readable as the first expression :-(