2015-08-24 85 views
20

我有兩個布爾列表,例如,兩個布爾列表上的Python AND運算符 - 如何?

x=[True,True,False,False] 
y=[True,False,True,False] 

我想和這些列表一起,與預期輸出:

xy=[True,False,False,False] 

我認爲表達x and y會的工作,但來到發現它沒有:其實,(x and y) != (y and x)

x and y輸出:[True,False,True,False]

輸出的y and x[True,True,False,False]

使用列表理解確實有正確的輸出。呼!

xy = [x[i] and y[i] for i in range(len(x)] 

請注意,我找不到任何引用告訴我AND運算符會按照我嘗試使用x和y的方式工作。但在Python中嘗試事情很容易。 有人可以向我解釋x and y發生了什麼?

這裏是一個簡單的測試程序:

import random 
random.seed() 
n = 10 
x = [random.random() > 0.5 for i in range(n)] 
y = [random.random() > 0.5 for i in range(n)] 
# Next two methods look sensible, but do not work 
a = x and y 
z = y and x 
# Next: apparently only the list comprehension method is correct 
xy = [x[i] and y[i] for i in range(n)] 
print 'x  : %s'%str(x) 
print 'y  : %s'%str(y) 
print 'x and y : %s'%str(a) 
print 'y and x : %s'%str(z) 
print '[x and y]: %s'%str(xy) 
+0

x是一個列表,y爲列表。當且僅當兩個列表都是非空的(空列表是'false-y',所有非空列表都是'真-y')時,'x和y'纔是真的:即'x和y'確實*不*'和每個元素'或其他關心值。 – user2864740

回答

26

and簡單地返回第一個或第二個操作數的基礎上,他們的真值。如果第一個操作數被認爲是false,則返回該操作數,否則返回另一個操作數。

名單被認爲是真正的,所以這兩個列表被認爲是真實的。他們的內容在這裏不起作用

因爲兩個列表都不是空的,所以x and y只是返回第二個列表對象;只有當x是空的會是什麼,而不是返回:

>>> [True, False] and ['foo', 'bar'] 
['foo', 'bar'] 
>>> [] and ['foo', 'bar'] 
[] 

Truth value testing section Python文檔中:

任何對象都可以對真值進行測試,用在ifwhile狀況或作爲下面布爾運算的操作數。下面的值被認爲是假:

[...]

  • 任何空序列,例如,''()[]

[...]

所有其他值都認爲是真 - 這麼多類型的對象總是如此。

(重點煤礦),以及Boolean operations section正下方是:

x and y
如果X是假的,那麼X,否則ÿ

這是一個短路運算符,所以它只評估第二個參數,如果第一個參數是True

您確實需要在列表中明確測試包含的值。正如你發現的那樣,你可以用列表理解來實現。您可以用zip() function改寫它配對的值:

[a and b for a, b in zip(x, y)] 
+1

感謝您的優秀解釋和特別。重複我所看到的「如果x是假的,那麼x,否則y」,但沒有完全保持。這是RTFM的情況,我應該仔細閱讀它! –

2

這應該做你想要什麼:

xy = [a and b for a, b in zip(x, y)] 

原因x and y回報yy and x回報x是因爲在Python布爾運算符返回檢查最後一個值,確定表達式的真實性。非空list的計算結果爲True,並且由於and要求兩個操作數都評估True,所以檢查的最後一個操作數是第二個操作數。與x or y對比,這將返回x,因爲它不需要檢查y以確定表達式的真實性。

0

可以使用zip功能

x=[True,True,False,False] 
y=[True,False,True,False] 
z=[a and b for a,b in zip(x,y)] 
4

and不一定是布爾運算符;它將返回其兩個參數中的一個,而不管它們的類型如何。如果第一個參數是false-ish(False,數字零或空字符串/容器),則返回該參數。否則,它返回第二個參數。

在你的情況下,兩個xy非空列表,所以第一個參數始終是真實的十歲上下,這意味着x and y回報yy and x回報x

6

你可以使用numpy的:

>>> import numpy as np 
>>> x=np.array([True,True,False,False]) 
>>> y=np.array([True,False,True,False]) 
>>> x & y 
array([ True, False, False, False], dtype=bool) 

numpy的允許在陣列數字和邏輯運算,例如:

>>> z=np.array([1,2,3,4]) 
>>> z+1 
array([2, 3, 4, 5]) 

可以進行按位和與&運營商。

取代列表解析,你可以使用numpy的生成布爾數組直接像這樣:

>>> np.random.random(10)>.5 
array([ True, True, True, False, False, True, True, False, False, False], dtype=bool) 
0

而不是使用

[a and b for a, b in zip(x, y)] 

一個可以只使用numpy的可能性乘以bool-values:

(np.array(x)*np.array(y)) 
>> array([ True, False, False, False], dtype=bool) 

或者我忽略了一個特例?

0

除了什麼@Martijn皮特斯已經回答了,我只想添加以下代碼,以行動說明andor操作。

and返回否則遇到的最後一個變量第一falsy值。

同樣or返回否則遇到的最後一個變量第一truthy值。

nl1 = [3,3,3,3,0,0,0,0] 
nl2 = [2,2,0,0,2,2,0,0] 
nl3 = [1,0,1,0,1,0,1,0] 
and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)] 
or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)] 

值是

and_list = [1, 0, 0, 0, 0, 0, 0, 0]

or_list = [3, 3, 3, 3, 2, 2, 1, 0]