'and' (logiczny) vs ' & ' (bitowy) - dlaczego różnica w zachowaniu list vs tablic numpy?

Co wyjaśnia różnicę w zachowaniu operacji logicznych i bitowych na listach vs tablicach NumPy?

Jestem zdezorientowany co do właściwego użycia & vs and w Pythonie, co zilustrowano poniższymi przykładami.

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!

Ta odpowiedź i ta odpowiedź pomogła mi zrozumieć, że and jest operacją logiczną, ale & jest operacją bitową.

Czytałem o operacjach bitowych aby lepiej zrozumieć tę koncepcję, ale staram się wykorzystać te informacje, aby nadać sens moim powyższym przykładom 4.

Przykład 4 doprowadził mnie do pożądanego wyniku, więc jest to w porządku, ale nadal Nie wiem, kiedy/jak / dlaczego powinienem użyć and vs &. Dlaczego listy i tablice NumPy zachowują się inaczej z tymi operatorami?

Czy ktoś może mi pomóc zrozumieć różnicę między operacjami logicznymi i bitowymi, aby wyjaśnić, dlaczego inaczej obsługują listy i tablice NumPy?

Author: wjandrea, 2014-03-25

8 answers

and sprawdza czy oba wyrażenia są logiczne True while & (Gdy używane są z True/False wartości) sprawdza, czy oba są True.

W Pythonie puste wbudowane obiekty są zwykle traktowane jako logiczne False, podczas gdy niepuste wbudowane są logiczne True. Ułatwia to powszechny przypadek użycia, w którym chcesz zrobić coś, jeśli lista jest pusta, a coś innego, jeśli lista nie jest. Zauważ, że oznacza to, że lista [False] jest logiczna True:

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

Więc w przykładzie 1, pierwsza lista jest niepustaĺ 'a, a wiÄ ™ c logicznie True, wiÄ ™ c wartoĹ" Ä ‡ prawdy and jest taka sama jak wartoĹ " Ä ‡ drugiej listy. (W naszym przypadku druga lista jest niepustaĺ 'a, a wiÄ ™ c logicznie True, ale jej zidentyfikowanie wymagaĹ' oby niepotrzebnego kroku kalkulacji.)

Na przykład 2, listy nie mogą być w sposób znaczący łączone w sposób bitowy, ponieważ mogą zawierać dowolne elementy w przeciwieństwie do nich. Rzeczy, które można połączyć bitowo to: Trues i Falses, liczby całkowite.

Obiekty NumPy natomiast wspierają wektorowe obliczenia. Oznacza to, że pozwalają wykonywać te same operacje na wielu fragmentach danych.

Przykład 3 nie powiedzie się, ponieważ tablice NumPy (o długości > 1) nie mają wartości prawdy, ponieważ zapobiega to zamieszaniu logiki opartej na wektorach.

Przykład 4 jest po prostu wektoryzowanym bitem and operacji.

Bottom Line

  • Jeśli nie masz do czynienia z tablicami i nie wykonujesz matematyki manipulacje liczbami całkowitymi, prawdopodobnie chcesz and.

  • Jeśli masz wektory wartości prawdy, które chcesz połączyć, użyj numpy z &.

 128
Author: ramcdougal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 21:47:12

O list

Najpierw bardzo ważny punkt, z którego wszystko będzie (mam nadzieję).

W zwykłym Pythonie, list nie jest w żaden sposób wyjątkowy(poza ładną składnią do konstruowania, która jest w większości wypadkiem historycznym). Po utworzeniu listy [3,2,6], jest ona zwykłym obiektem Pythona, takim jak liczba 3, set {3,7} lub Funkcja lambda x: x+5.

(tak, wspiera zmianę swoich elementów, wspiera iterację i wiele inne rzeczy, ale tym właśnie jest typ: obsługuje niektóre operacje, podczas gdy nie obsługuje innych. int wspiera podnoszenie do potęgi, ale to nie czyni go wyjątkowym - po prostu tym, czym jest int. lambda wspiera wywoływanie, ale to nie czyni go wyjątkowym - przecież po to jest lambda:).

O and

and nie jest operatorem (można go nazwać "operatorem", ale można też nazwać "dla" operatora:). Operatory w Pythonie są (zaimplementowane poprzez) metody wywoływane na obiektach jakiegoś typu, zwykle zapisywane jako część tego typu. Nie ma sposobu, aby metoda mogła przeprowadzić ocenę niektórych jej operandów, ale and może (i musi) to zrobić.

Konsekwencją tego jest to, że and nie może być przeciążony, tak jak for nie może być przeciążony. Jest całkowicie ogólny i komunikuje się za pośrednictwem określonego protokołu. To, co możesz zrobić, to dostosować swoją część protokołu, ale to nie znaczy, że możesz zmienić zachowanie and całkowicie. Protokół jest następujący:

Wyobraź sobie, że Python interpretuje "a i b" (nie dzieje się to dosłownie w ten sposób, ale pomaga zrozumieć). Jeśli chodzi o "and", patrzy na obiekt, który właśnie ocenił (a) i pyta go: czy to prawda? (Nie : jesteś True?) Jeśli jesteś autorem klasy a, możesz dostosować tę odpowiedź. Jeśli a odpowiada "Nie", and (pomija b całkowicie, w ogóle nie jest oceniana i) mówi: a jest moim wynikiem ( Nie : False jest moim wynik).

Jeśli a nie odpowiada, and pyta: jaka jest twoja długość? (Ponownie możesz to dostosować jako autor klasy a). Jeśli a odpowiada 0, and robi to samo, co powyżej - uważa to za false (Nie False), pomija b i daje a jako wynik.

Jeśli a odpowie coś innego niż 0 Na drugie pytanie ("Jaka jest twoja długość"), lub w ogóle nie odpowiada, lub odpowiada "tak" na pierwsze ("czy jesteś prawdziwy"), and ocenia b i mówi:: b to mój wynik. Zauważ, że to nie zadaje b jakiekolwiek pytania.

Innym sposobem na stwierdzenie tego wszystkiego jest to, że a and b jest prawie takie samo jak b if a else a, z tym, że a jest oceniane tylko raz.

Teraz usiądź na kilka minut z długopisem i papierem i przekonaj się, że gdy {A, b} jest podzbiorem {True, False}, działa dokładnie tak, jak można oczekiwać od operatorów logicznych. Ale mam nadzieję, że przekonałem cię, że jest to o wiele bardziej ogólne, i jak zobaczysz, o wiele bardziej przydatne to sposób.

Składanie tych dwóch razem

Teraz mam nadzieję, że rozumiesz swój przykład 1. and nie obchodzi czy mylist1 jest liczbą, listą, lambda czy obiektem klasy Argmhbl. Zależy tylko na odpowiedzi mylist1 na pytania protokołu. I oczywiście mylist1 odpowiada 5 na pytanie o długość, więc i zwraca mylist2. I to wszystko. Nie ma to nic wspólnego z elementami mylist1 i mylist2 - nigdzie nie wchodzą w obraz.

Drugi przykład: & on list

Z drugiej strony, & jest operatorem jak każdy inny, jak na przykład +. Może być zdefiniowana dla typu poprzez zdefiniowanie specjalnej metody na tej klasie. int definiuje je jako bitowe "i", a bool definiuje je jako logiczne "i", ale to tylko jedna z opcji: na przykład zestawy i niektóre inne obiekty, takie jak widoki kluczy dict, definiują je jako zbiór przecięć. list po prostu tego nie definiuje, prawdopodobnie dlatego, że Guido nie wpadł na żaden oczywisty sposób definiowania to.

Numpy

Na drugiej nodze: - D, tablice numpy specjalne, a przynajmniej starają się być. Oczywiście, numpy.array jest tylko klasą, nie może w żaden sposób nadpisać and, więc robi następną najlepszą rzecz: gdy zapytamy "czy jesteś prawdziwy", numpy.array podnosi ValueError, skutecznie mówiąc "Proszę przeformułować pytanie, mój pogląd na prawdę nie pasuje do twojego modelu". (Zauważ, że wiadomość ValueError nie mówi o and - ponieważ numpy.array nie wie Kto zadaje mu pytanie; to po prostu mówi o prawdzie.)

Dla &, to zupełnie inna historia. numpy.array może definiować go tak, jak chce i definiuje & konsekwentnie z innymi operatorami: pointwise. Więc w końcu dostajesz to, czego chcesz.

HTH,

 29
Author: Veky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 06:50:25

Zwarte operatory logiczne (and, or) nie można tego przesłonić, ponieważ nie ma satysfakcjonującego sposobu, aby to zrobić bez wprowadzenia nowych funkcji językowych lub poświęcenia zwarcia. Jak możesz lub nie wiesz, oceniają One pierwszy argument pod kątem jego wartości prawdy i w zależności od tej wartości, albo oceniają i zwracają drugi argument, albo nie oceniają drugiego argumentu i zwracają pierwszy: {]}

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

Zauważ, że (wynik oceny) rzeczywistego operandu jest zwrócona, a nie wartość prawdy.

Jedynym sposobem dostosowania ich zachowania jest nadpisanie __nonzero__ (przemianowane na __bool__ w Pythonie 3), dzięki czemu możesz wpływać na to, który operand zostanie zwrócony, ale nie zwracać czegoś innego. Listy (i inne zbiory) są definiowane jako "prawdziwe", gdy zawierają cokolwiek, i "fałszywe", gdy są puste.

Tablice NumPy odrzucają to pojęcie: dla przypadków użycia, do których zmierzają, dwa różne pojęcia prawdy są wspólne: (1) Czy jakikolwiek element jest true, oraz (2) czy wszystkie elementy są prawdziwe. Ponieważ te dwa są całkowicie (i po cichu) niezgodne, A żadne z nich nie jest wyraźnie poprawniejsze lub bardziej powszechne, NumPy odmawia zgadywania i wymaga od Ciebie wyraźnego użycia .any() lub .all().

& i | (i not, przy okazji) mogą być w pełni nadpisane, ponieważ nie powodują zwarcia. Mogą zwracać wszystko, gdy są nadpisane, a NumPy dobrze wykorzystuje to do wykonywania operacji związanych z elementami, tak jak w przypadku praktycznie każdego innego operacja skalarna. Listy, z drugiej strony, nie transmitują operacji na swoich elementach. Tak jak {[10] }nic nie znaczy, a mylist1 + mylist2 oznacza coś zupełnie innego, nie ma operatora & dla list.

 23
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 21:49:54

Przykład 1:

Tak działa operator i .

x i y => if x is false, then x , else y

Innymi słowy, ponieważ mylist1 nie jest False, wynikiem wyrażenia jest mylist2. (Tylko puste listy oceniają na False.)

Przykład 2:

Operator & jest dla bitowego i, jak wspominasz. Operacje bitowe działają tylko na liczby. Wynik a & b jest liczbą składającą się z 1s w bitach, które są 1 w a i b . Na przykład:

>>> 3 & 1
1

Łatwiej jest zobaczyć, co się dzieje, używając binarnego literału (te same liczby, co powyżej):

>>> 0b0011 & 0b0001
0b0001

Operacje bitowe są podobne koncepcyjnie do operacji boolean( truth), ale działają tylko na bitach.

Więc, biorąc pod uwagę kilka oświadczeń o moim samochodzie

  1. mój samochód jest czerwony
  2. mój samochód ma koła

Logiczne "i" tych dwóch twierdzeń to:

(Czy mój samochód jest czerwony?) i (czy samochód ma koła?) = > logiczna prawda o wartości false

Oba są prawdziwe, przynajmniej dla mojego samochodu. Tak więc wartość twierdzenia jako całości jest logicznie true.

Bitowe "i" tych dwóch stwierdzeń jest nieco bardziej mgliste:

(wartość liczbowa polecenia 'my car is red') & (wartość liczbowa stwierdzenie 'mój samochód ma koła') = > Numer

Jeśli python wie, jak przekonwertować polecenia na wartości liczbowe, to zrobi to i obliczy bitowe-i obu wartości. Może to prowadzić do przekonania, że {[6] } jest wymienne z and, ale tak jak w powyższym przykładzie są to różne rzeczy. Ponadto, dla obiektów, które nie mogą zostać przekonwertowane, otrzymasz po prostu TypeError.

Przykład 3 i 4:

Numpy implementuje arytmetykę operacje dla tablic:

Operacje arytmetyczne i porównawcze na ndarrays są definiowane jako operacje elementowe i ogólnie dają obiekty ndarray jako wyniki.

Ale nie implementuje operacji logicznych dla tablic, ponieważ nie można przeciążać operatorów logicznych w Pythonie . Dlatego przykład trzeci nie działa, ale przykład czwarty tak.

Aby odpowiedzieć na twoje and vs & pytanie: użyj and.

Operacje bitowe są używane do badania struktury liczby (które bity są ustawione, które bity nie są ustawione). Ten rodzaj informacji jest najczęściej używany w niskopoziomowych interfejsach systemu operacyjnego (na przykładbity uprawnień Uniksa). Większość programów Pythona nie musi tego wiedzieć.

Operacje logiczne(and, or, not), jednak są używane przez cały czas.

 17
Author: Seth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:25
  1. W Pythonie wyrażenie X and Y zwraca Y, biorąc pod uwagę, że bool(X) == True lub którykolwiek z X lub Y ocenia Na False, np.:

    True and 20 
    >>> 20
    
    False and 20
    >>> False
    
    20 and []
    >>> []
    
  2. Operator bitowy nie jest po prostu zdefiniowany dla list. Jest on jednak zdefiniowany dla liczb całkowitych-operujących na binarnej reprezentacji liczb. Rozważmy 16 (01000) i 31 (11111):

    16 & 31
    >>> 16
    
  3. NumPy nie jest medium, nie wie, czy masz na myśli, że np. [False, False] powinno być równe True w logicznym ekspresja. W ten sposób nadpisuje standardowe zachowanie Pythona, które brzmi: "każda pusta kolekcja z len(collection) == 0 jest False".

  4. Prawdopodobnie oczekiwane zachowanie operatora & tablic NumPy.

 16
Author: Zaur Nasibov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-22 11:06:29

Dla pierwszego przykładu i bazuj na doc django
Zawsze zwróci drugą listę, w rzeczywistości nie pusta lista jest postrzegana jako wartość True dla Pythona, więc python zwraca "ostatnią" wartość True, więc druga lista

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
Author: MoiTux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 22:40:01

Operacje z listą Pythona działają na liście . list1 and list2 sprawdzi, czy list1 jest pusta i zwróci list1, jeśli jest, i list2, Jeśli nie jest. list1 + list2 doda list2 do list1, więc otrzymasz nową listę z elementami len(list1) + len(list2).

Operatory

, które mają sens tylko wtedy, gdy są stosowane w elementach, takie jak &, wywołują TypeError, ponieważ operacje elementowe nie są obsługiwane bez zapętlenia elementów.

Tablice Numpy obsługują operacje oparte na elementach . array1 & array2 obliczy bit lub dla każdego odpowiedniego elementu w array1 i array2. array1 + array2 obliczy sumę dla każdego odpowiedniego elementu w array1 i array2.

To nie działa dla and i or.

array1 and array2 jest zasadniczo krótką ręką dla następującego kodu:

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

Do tego potrzebujesz dobrej definicji bool(array1). Dla operacji globalnych, takich jak używane na listach Pythona, definicja jest taka, że bool(list) == True jeśli list nie jest pusta, a False jeśli jest pusta. Na numpy ' s element-wise operations, there is some disambiguity whether to check if any element evaluates to True, or all elements evaluates to True. Ponieważ oba są prawdopodobnie poprawne, numpy nie zgaduje i podnosi ValueError, gdy bool() jest (pośrednio) wywoływane na tablicy.

 4
Author: knbk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 06:57:13

Dobre pytanie. Podobnie do spostrzeżenia masz o przykładach 1 i 4 (lub powinienem powiedzieć 1 i 4:)) nad operatorami logicznymi and bitowymi &, doświadczyłem na operatorze sum. Numpy sum i Py sum zachowują się również inaczej. Na przykład:

Załóżmy, że " mat " jest tablicą numpy 5x5 2d, taką jak:

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

Potem numpy.sum (mat) daje całkowitą sumę całej macierzy. Podczas gdy wbudowana suma z Pythona, taka jak sum (mat), wynosi tylko wzdłuż osi. Patrz poniżej:

np.sum(mat)  ## --> gives 325
sum(mat)     ## --> gives array([55, 60, 65, 70, 75])
 0
Author: S.S.Prabhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-15 14:07:30