'and'(boolean) vs '&'(bitwise)-왜리스트와 numpy 배열의 동작에 차이가 있습니까?


142

목록과 NumPy 배열에서 부울 연산과 비트 연산의 동작의 차이점은 무엇입니까?

다음 예제와 같이 Python에서 &vs and를 올바르게 사용하는 것에 대해 혼란 스럽습니다 .

mylist1 = [True,  True,  True, False,  True]
mylist2 = [False, True, False,  True, False]

>>> len(mylist1) == len(mylist2)
True

# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]

# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?

>>> import numpy as np

# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?

# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False,  True, False, False, False], dtype=bool)
# This is the output I was expecting!

이 답변 하고 ,이 대답은 나를 이해 도움이 and부울 동작하지만, &비트 연산이다.

개념을 더 잘 이해하기 위해 비트 단위 연산 에 대해 읽었 지만 위의 4 가지 예를 이해하기 위해 해당 정보를 사용하는 데 어려움을 겪고 있습니다.

즉 괜찮지 만, 나는 아직도 내가 어떻게 / 사용해야하는 이유 때 /에 대해 혼란 스러워요 그래서 예 4, 내 원하는 출력를 알려준 and& . 왜리스트와 NumPy 배열이이 연산자들과 다르게 동작합니까?

부울 연산과 비트 연산의 차이점을 이해하여 왜 목록과 NumPy 배열을 다르게 처리하는지 설명 할 수 있습니까?


2
NumPy와에서 거기 np.bitwise_and()np.logical_and()친구 혼동을 피하기 위해.
Dietrich

1
예제 1에서 반환되는 것은 delnan이 지적한 두 번째 목록이므로 예제 mylist1 and mylist2와 동일한 결과를 출력하지 않습니다 mylist2 and mylist1.
user2015487

답변:


113

and두 표현식이 논리적 일 True&( True/ False값 과 함께 사용될 때) 두 표현식이 모두 논리적인지 테스트합니다.True .

파이썬에서 빈 내장 객체는 일반적으로 논리적으로 처리되는 False반면 비어 있지 않은 내장 객체는 논리적으로 처리됩니다 True. 이렇게하면 목록이 비어있는 경우 목록이 아닌 경우 다른 작업을 수행하려는 일반적인 사용 사례가 용이 해집니다. 이는 [False] 목록이 논리적으로 True다음을 의미합니다 .

>>> if [False]:
...    print 'True'
...
True

따라서 예 1에서 첫 번째 목록은 비어 있지 않으므로 논리적으로 True이므로의 실제 값은 and두 번째 목록의 값과 같습니다. (우리의 경우 두 번째 목록은 비어 있지 않으므로 논리적으로 True불필요하지만이를 계산하는 데 불필요한 계산 단계가 필요합니다.)

예를 들어, 2는리스트가 임의의 다른 요소를 포함 할 수 있기 때문에 비트 단위로 의미있게 결합 될 수 없습니다. 비트 단위로 결합 할 수있는 것은 True와 Fales, 정수입니다.

이와 반대로 NumPy 객체는 벡터화 된 계산을 지원합니다. 즉, 여러 데이터 조각에 대해 동일한 작업을 수행 할 수 있습니다.

길이가 1보다 큰 NumPy 배열은 벡터 기반 논리 혼동을 막기 때문에 진리 값이 없으므로 예제 3이 실패합니다.

예제 4는 단순히 벡터화 된 비트 and연산입니다.

결론

  • 배열을 다루지 않고 정수의 수학 조작을 수행하지 않는 경우을 원할 것 and입니다.

  • 결합하려는 진리 값 벡터가있는 경우 numpy와 함께 사용하십시오 &.


27

list

먼저 모든 것이 뒤따를 매우 중요한 요점입니다.

일반적인 파이썬에서는 list어떤 식 으로든 특별하지 않습니다 (주로 역사적 사고 인 구성을위한 귀여운 구문을 제외하고). 일단리스트 [3,2,6]가 만들어지면, 그것은 모든 의도와 목적을위한 숫자 3, set {3,7}또는 함수 와 같은 일반적인 파이썬 객체 일뿐 lambda x: x+5입니다.

(예, 요소 변경을 지원하고 반복 및 기타 여러 가지를 지원하지만 유형이 바로 그저 유형입니다. 일부 작업은 지원하지만 일부는 지원하지 않습니다. 람다는 호출을 지원하지만 람다는 그것이 람다의 목적입니다 :).

and

and연산자가 아닙니다 ( "operator"라고 부를 수 있지만 연산자를 "for"라고 부를 수도 있습니다). 파이썬의 연산자는 일반적으로 해당 유형의 일부로 작성된 일부 유형의 객체에서 호출되는 (구현 된) 메소드입니다. 메소드가 피연산자의 일부를 평가할 수있는 방법은 없지만 그렇게 and할 수는 있습니다.

그 결과 and오버로드 for할 수없는 것처럼 오버로드 할 수 없습니다. 완전히 일반적이며 지정된 프로토콜을 통해 통신합니다. 할 수있는 일은 프로토콜의 일부를 사용자 지정하는 것이지만, 동작을 and완전히 변경할 수는 없습니다 . 프로토콜은 다음과 같습니다

파이썬이 "a와 b"를 해석한다고 상상해보십시오 (이것은 문자 그대로 이런 방식으로 발생하지 않지만 이해하는 데 도움이됩니다). "and"에 관해서는, 방금 평가 한 대상을보고 (a) 묻습니다. 당신은 사실입니까? ( NOT : are you True?) 수업의 저자 인 경우이 답변을 사용자 정의 할 수 있습니다. a"아니오"라고 대답 하면 and(b가 완전히 건너 뛰고 전혀 평가되지 않으며) a내 결과입니다 ( Not : False is my result).

경우 a에 응답하지 않습니다, and그것을 요청 : 당신의 길이는 무엇인가? (이 a클래스 의 작성자로 이것을 사용자 지정할 수 있습니다 ). a0으로 대답 하면 and위와 동일합니다-거짓으로 간주하고 ( NOT False) b를 건너 뛰고 a결과를 제공합니다 .

경우 a두 번째 질문에 0이 아닌 다른 답변 뭔가 ( "당신의 길이 무엇인가"), 또는 전혀 응답하지 않거나은 첫 번째 ( "당신은 참 ')"예 "라고 대답, andB를 평가하고, 말한다 : b내 결과입니다. 그것은 않습니다 NOT 에게 b질문.

이 모든 것을 말하는 다른 방법 a and bb if a else aa가 한 번만 평가된다는 점을 제외하고 는 거의 동일 합니다.

이제 펜과 종이로 몇 분 동안 앉아 {a, b}가 {True, False}의 하위 집합 일 때 부울 연산자에 대해 예상 한대로 작동한다는 것을 확신하십시오. 그러나 나는 그것이 당신이 훨씬 더 일반적이고 당신이 볼 수 있듯이이 방법으로 훨씬 더 유용하다는 것을 확신하기를 바랍니다.

이 두 가지를 함께

이제 예제 1을 이해하기를 바랍니다. andmylist1이 숫자, 목록, 람다 또는 Argmhbl 클래스의 객체인지 상관하지 않습니다. 그것은 프로토콜의 질문에 대한 mylist1의 대답에만 관심이 있습니다. 물론, mylist1은 길이에 대한 질문에 5로 대답하여 mylist2를 반환합니다. 그리고 그게 다야. mylist1 및 mylist2의 요소와는 아무런 관련이 없습니다. 그들은 어디에도 그림을 입력하지 않습니다.

두 번째 예 : &켜기list

한편 &, 예 +를 들어 다른 것과 같은 연산자 입니다. 해당 클래스에 특수 메소드를 정의하여 유형에 대해 정의 할 수 있습니다. int비트 단위 "and"로 정의하고 부울은 논리 "and"로 정의하지만 이는 하나의 옵션입니다. listGuido가 정의하는 명확한 방법을 생각하지 않았기 때문에 정의하지 않았습니다.

numpy

다른 다리 :-D에서, numpy 배열 특별하거나 적어도 노력하고 있습니다. 물론 numpy.array는 클래스 일 뿐이며 and어떤 식 으로든 재정의 할 수 없으므로 다음과 같은 최선의 방법을 수행합니다. "정말입니까?" 진실의 관점은 당신의 모델에 맞지 않습니다 ". andnumpy.array는 누가 질문을 하는지 모르기 때문에 진실에 대해서만 이야기 하기 때문에 ValueError 메시지는 언급하지 않습니다 .

에 대해서는 &완전히 다른 이야기입니다. numpy.array는 원하는대로 정의 할 수 &있으며 다른 연산자와 일관되게 정의합니다 . 그래서 당신은 마침내 당신이 원하는 것을 얻습니다.

HTH,


23

단락 부울 연산자 ( and, or)는 새로운 언어 기능을 도입하거나 단락을 희생하지 않고는이를 수행 할 수있는 만족스러운 방법이 없기 때문에 재정의 할 수 없습니다. 당신이 알거나 모르는 것처럼, 그들은 첫 번째 피연산자의 진가를 평가하고 그 값에 따라 두 번째 인수를 평가하고 반환하거나 두 번째 인수를 평가하지 않고 첫 번째 인수를 반환합니다.

something_true and x -> x
something_false and x -> something_false
something_true or x -> something_true
something_false or x -> x

실제 피연산자 (평가 결과)는 실제 값이 아니라 반환됩니다.

동작을 사용자 정의하는 유일한 방법은 재정의 __nonzero__(__bool__ Python 3에서 in). 따라서 어떤 피연산자가 리턴되는지에 영향을 줄 수 있지만 다른 것을 리턴하지는 않습니다. 목록 (및 기타 컬렉션)은 아무 것도 포함되어 있으면 "거짓"으로 표시되고 비어 있으면 "거짓"으로 정의됩니다.

NumPy 배열은 이러한 개념을 거부합니다. 사용 사례의 경우 두 가지 다른 진리 개념이 일반적입니다. (1) 어떤 요소가 참인지, (2) 모든 요소가 참인지. 이 두 가지가 완전히 (조용히) 호환되지 않는, 그리고 어느 쪽도 분명히 더 정확한 이상의 공통 없기 때문에, NumPy와 추측을 거부하고 명시 적으로 사용하도록 요구 .any()하거나 .all().

&그리고 |(그리고 not) 그들은 단락되지 않기 때문에 완전히 재정의 될 있습니다. 오버라이드 될 때 아무것도 반환 할 수 없으며 NumPy는 실제로 다른 스칼라 연산과 마찬가지로 요소 별 연산을 수행하기 위해 NumPy를 잘 사용합니다. 반면에 목록은 요소 전체에서 작업을 브로드 캐스트하지 않습니다. 마찬가지로 mylist1 - mylist2하지 평균 아무것도하지 mylist1 + mylist2, 완전히 다른 수단 무언가를 더이없는 &목록에 대한 연산자.


3
이것이 생산할 수있는 것의 특히 흥미로운 예는로 [False] or [True]평가 [False]하고로 [False] and [True]평가합니다 [True].
Rob Watts

16

예 1 :

이것이 and 연산자의 작동 방식입니다.

xy => x 가 false이면 x , 그렇지 않으면 y

다시 말해, mylist1is가 아니기 때문에 False식의 결과는 mylist2입니다. ( 빈 목록 만 평가됩니다 False.)

예 2 :

&당신이 언급으로 연산자는 비트 용이고. 비트 단위 연산은 숫자에서만 작동합니다. 결과 및 B는 모두 1 비트이다 1S 이루어지는 번호 및 B . 예를 들면 다음과 같습니다.

>>> 3 & 1
1

이진 리터럴 (위와 같은 숫자)을 사용하여 어떤 일이 일어나고 있는지 쉽게 알 수 있습니다 .

>>> 0b0011 & 0b0001
0b0001

비트 단위 연산은 개념적으로 부울 (진리) 연산과 유사하지만 비트에서만 작동합니다.

그래서 내 차에 대한 몇 가지 진술이 주어지면

  1. 내 차는 빨간색
  2. 내 차에 바퀴가있다

이 두 문장의 논리적 "and"는 다음과 같습니다.

(내 차가 빨간색입니까?) 및 (차에 바퀴가 있습니까?) => 논리 값이 거짓 임

적어도 내 차에는 둘 다 사실입니다. 따라서 진술의 가치는 논리적으로 사실입니다.

이 두 문장의 비트 단위 "and"는 조금 더 성실합니다.

( '내 차는 빨간색입니다'문장의 숫자 값) 및 ( '내 차에는 바퀴가 있습니다'문장 숫자 값) => 숫자

파이썬이 문장을 숫자 값으로 변환하는 방법을 알고 있다면 그렇게하고 두 값의 비트 단위를 계산합니다. 이것은 당신이 &와 상호 교환 가능 하다고 믿게 만들 수 and있지만, 위의 예와 같이 그것들은 다릅니다. 또한 변환 할 수없는 객체의 경우을 얻을 수 있습니다 TypeError.

실시 예 3 및 4 :

Numpy 는 배열에 대한 산술 연산 을 구현 합니다.

ndarray의 산술 및 비교 연산은 요소 별 연산으로 정의되며 일반적으로 ndarray 객체를 결과로 생성합니다.

그러나 파이썬에서 논리 연산자를 오버로드 없기 때문에 배열에 대한 논리 연산을 구현하지 않습니다 . 그렇기 때문에 예제 3은 작동하지 않지만 예제 4는 작동하지 않습니다.

따라서 귀하의 andvs &질문 에 대답 하려면 : 사용하십시오 and.

비트 단위 연산은 숫자의 구조 (어떤 비트가 설정되고 어떤 비트가 설정되지 않은지)를 검사하는 데 사용됩니다. 이러한 종류의 정보는 주로 저수준 운영 체제 인터페이스 ( 예 : 유닉스 권한 비트 )에서 사용됩니다. 대부분의 파이썬 프로그램은 그 사실을 알 필요가 없습니다.

논리적 작업 ( and, or, not)하지만, 모든 시간을 사용한다.


14
  1. 파이썬에서 X and Yreturns Y, bool(X) == True또는 그 중 하나 X또는 YFalse로 평가 되는 표현식은 다음과 같습니다.

    True and 20 
    >>> 20
    
    False and 20
    >>> False
    
    20 and []
    >>> []
  2. 비트 연산자는 단순히 목록에 대해 정의되지 않았습니다. 그러나 정수에 대해 정의됩니다-숫자의 이진 표현을 통해 작동합니다. 16 (01000) 및 31 (11111)을 고려하십시오.

    16 & 31
    >>> 16
  3. NumPy는 심령이 아니며, 예를 들어 논리적 표현에서 [False, False]동일해야 한다는 것을 의미하는지 여부는 알 수 없습니다 True. 여기서는 표준 Python 동작을 재정의합니다. "가있는 빈 컬렉션 len(collection) == 0False"입니다.

  4. 아마도 NumPy의 배열 및 연산자의 예상되는 동작입니다.


거짓과 (20 개)는 false를 반환
라훌

4

django의 doc 에 대한 첫 번째 예제와 기반
경우 항상 두 번째 목록을 반환합니다. 실제로 비어 있지 않은 목록은 Python의 True 값으로 간주되므로 Python은 '마지막'True 값을 반환하므로 두 번째 목록

In [74]: mylist1 = [False]
In [75]: mylist2 = [False, True, False,  True, False]
In [76]: mylist1 and mylist2
Out[76]: [False, True, False, True, False]
In [77]: mylist2 and mylist1
Out[77]: [False]

4

파이썬리스트를 사용한 연산은리스트에서 작동 합니다 . 비어 list1 and list2있는지 확인하고 list1비어 있으면 반환 list1합니다 list2. list1 + list2추가합니다 list2으로 list1당신이 새로운 목록을 얻을 수 있도록, len(list1) + len(list2)요소.

와 같이 요소별로 적용 할 때만 의미가있는 연산자 &TypeError 소자 연산의 경우로는 상기 요소들을 반복하지 않고 지원되지 않는다.

Numpy 어레이는 요소 별 작업을 지원 합니다. array1 & array2비트 단위를 계산하거나 각에 대응하는 요소에 대한 것이다 array1array2. 및의 array1 + array2각 해당 요소에 대한 합계를 계산합니다 .array1array2

이 작동하지 않습니다 andor.

array1 and array2 본질적으로 다음 코드의 줄임말입니다.

if bool(array1):
    return array2
else:
    return array1

이를 위해서는의 좋은 정의가 필요합니다 bool(array1). Python 목록에서 사용되는 것과 같은 전역 작업의 bool(list) == True경우 정의는 list비어 있지 않고 비어있는 경우 입니다 False. numpy의 요소 별 연산의 경우 요소가로 평가되는지 True또는 모든 요소가로 평가 되는지 확인해야합니다 True. 둘 다 틀림없이 정확하기 때문에 numpy는 배열에서 ValueError언제 bool()(간접적으로) 호출 되는지 추측하지 않고 발생 시킵니다.


0

좋은 질문. 논리 and비트 &연산자 에 대한 예제 1 및 4 (또는 1 & 4 :)라고 말한 관찰과 유사하게 연산자에서 경험했습니다 sum. numpy sum와 py도 sum다르게 동작합니다. 예를 들면 다음과 같습니다.

"mat"이 다음과 같은 numpy 5x5 2d 배열이라고 가정하십시오.

array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10],
       [11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20],
       [21, 22, 23, 24, 25]])

그런 다음 numpy.sum (mat)은 전체 행렬의 총합을 제공합니다. sum (mat)와 같은 Python의 내장 합계는 축을 따라 합계됩니다. 아래를보십시오 :

np.sum(mat)  ## --> gives 325
sum(mat)     ## --> gives array([55, 60, 65, 70, 75])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.