Apa yang menjelaskan perbedaan perilaku operasi boolean dan bitwise pada daftar vs array NumPy?
Saya bingung tentang penggunaan yang tepat dari &
vs and
di Python, diilustrasikan dalam contoh berikut.
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!
Jawaban ini dan jawaban ini membantu saya memahami bahwa and
ini adalah operasi boolean tetapi &
operasi bitwise.
Saya membaca tentang operasi bitwise untuk lebih memahami konsep, tetapi saya berjuang untuk menggunakan informasi itu untuk memahami 4 contoh di atas.
Contoh 4 menuntun saya untuk output saya diinginkan, sehingga baik-baik saja, tapi aku masih bingung tentang kapan / bagaimana / mengapa saya harus menggunakan and
vs &
. Mengapa daftar dan array NumPy berperilaku berbeda dengan operator ini?
Adakah yang bisa membantu saya memahami perbedaan antara operasi boolean dan bitwise untuk menjelaskan mengapa mereka menangani daftar dan array NumPy secara berbeda?
np.bitwise_and()
dannp.logical_and()
dan teman-teman untuk menghindari kebingungan.mylist1 and mylist2
tidak menampilkan hasil yang sama denganmylist2 and mylist1
, karena apa yang dikembalikan adalah daftar kedua seperti yang ditunjukkan oleh delnan.Jawaban:
and
menguji apakah kedua ekspresi secara logisTrue
sementara&
(ketika digunakan denganTrue
/False
nilai) menguji apakah keduanyaTrue
.Dalam Python, objek bawaan yang kosong biasanya diperlakukan secara logis
False
sedangkan bawaan yang tidak kosong secara logisTrue
. Ini memfasilitasi kasus penggunaan umum di mana Anda ingin melakukan sesuatu jika daftar kosong dan sesuatu yang lain jika daftar tidak. Perhatikan bahwa ini berarti bahwa daftar [Salah] secara logisTrue
:Jadi dalam Contoh 1, daftar pertama adalah kosong dan karenanya logis
True
, sehingga nilai kebenarannyaand
sama dengan daftar kedua. (Dalam kasus kami, daftar kedua tidak kosong dan karenanya secara logisTrue
, tetapi mengidentifikasi yang memerlukan langkah perhitungan yang tidak perlu.)Sebagai contoh 2, daftar tidak dapat digabungkan secara bermakna dalam cara bitwise karena mereka dapat mengandung unsur-unsur tidak seperti sewenang-wenang. Hal-hal yang dapat digabungkan dengan bitwise meliputi: Trues and Falses, integer.
Objek NumPy, sebaliknya, mendukung perhitungan vektor. Yaitu, mereka memungkinkan Anda melakukan operasi yang sama pada banyak bagian data.
Contoh 3 gagal karena array NumPy (panjang> 1) tidak memiliki nilai kebenaran karena ini mencegah kebingungan logika berbasis vektor.
Contoh 4 hanyalah
and
operasi bit vektor .Intinya
Jika Anda tidak berurusan dengan array dan tidak melakukan manipulasi matematika bilangan bulat, Anda mungkin ingin
and
.Jika Anda memiliki vektor nilai kebenaran yang ingin Anda gabungkan, gunakan
numpy
dengan&
.sumber
Tentang
list
Pertama, poin yang sangat penting, dari mana semuanya akan mengikuti (saya harap).
Dalam Python biasa,
list
tidak khusus dengan cara apa pun (kecuali memiliki sintaks lucu untuk membangun, yang sebagian besar merupakan kecelakaan historis). Setelah daftar[3,2,6]
dibuat, itu untuk semua maksud dan tujuan hanya objek Python biasa, seperti angka3
, set{3,7}
, atau fungsilambda x: x+5
.(Ya, ia mendukung pengubahan elemen-elemennya, dan mendukung iterasi, dan banyak hal lainnya, tetapi itulah jenisnya: ia mendukung beberapa operasi, sementara tidak mendukung beberapa yang lain. Int mendukung peningkatan daya, tetapi itu tidak buat itu sangat istimewa - itu hanya int. lambda mendukung pemanggilan, tapi itu tidak membuatnya sangat istimewa - itulah gunanya lambda :)
Tentang
and
and
bukan operator (Anda dapat menyebutnya "operator", tetapi Anda dapat memanggil "untuk" operator juga :). Operator di Python adalah (diimplementasikan melalui) metode yang dipanggil pada objek dari beberapa jenis, biasanya ditulis sebagai bagian dari jenis itu. Tidak ada cara bagi suatu metode untuk mengadakan evaluasi terhadap beberapa operandnya, tetapiand
dapat (dan harus) melakukannya.Konsekuensi dari itu adalah bahwa
and
tidak dapat kelebihan beban, sama sepertifor
tidak dapat kelebihan beban. Ini sepenuhnya umum, dan berkomunikasi melalui protokol yang ditentukan. Yang dapat Anda lakukan adalah menyesuaikan bagian protokol Anda, tetapi itu tidak berarti Anda dapat mengubah perilakuand
sepenuhnya. Protokolnya adalah:Bayangkan Python menafsirkan "a dan b" (ini tidak terjadi secara harfiah seperti ini, tetapi membantu memahami). Ketika datang ke "dan", itu melihat objek yang baru saja dievaluasi (a), dan bertanya: apakah Anda benar? ( BUKAN : apakah Anda
True
?) Jika Anda seorang penulis kelas a, Anda dapat menyesuaikan jawaban ini. Jikaa
jawaban "tidak",and
(melompati b sepenuhnya, itu tidak dievaluasi sama sekali, dan) mengatakan:a
adalah hasil saya ( BUKAN : Salah adalah hasil saya).Jika
a
tidak menjawab,and
tanyakan: berapa panjang Anda? (Sekali lagi, Anda dapat menyesuaikan ini sebagai penulisa
kelas). Jikaa
jawaban 0,and
lakukan hal yang sama seperti di atas - menganggapnya salah ( BUKAN Salah), lewati b, dan berikana
hasilnya.Jika
a
menjawab sesuatu selain 0 untuk pertanyaan kedua ("berapa panjang Anda"), atau tidak menjawab sama sekali, atau menjawab "ya" untuk pertanyaan pertama ("apakah Anda benar"),and
mengevaluasi b, dan mengatakan:b
adalah hasil saya. Perhatikan bahwa ia TIDAK mengajukanb
pertanyaan apa pun.Cara lain untuk mengatakan semua ini
a and b
adalah hampir sama denganb if a else a
, kecuali a dievaluasi hanya sekali.Sekarang duduk selama beberapa menit dengan pena dan kertas, dan yakinkan diri Anda bahwa ketika {a, b} adalah himpunan bagian dari {Benar, Salah}, itu berfungsi persis seperti yang Anda harapkan dari operator Boolean. Tetapi saya harap saya telah meyakinkan Anda bahwa itu jauh lebih umum, dan seperti yang akan Anda lihat, jauh lebih bermanfaat dengan cara ini.
Menyatukan keduanya
Sekarang saya harap Anda memahami contoh Anda 1.
and
tidak peduli apakah mylist1 adalah angka, daftar, lambda atau objek dari kelas Argmhbl. Itu hanya peduli tentang jawaban mylist1 untuk pertanyaan-pertanyaan protokol. Dan tentu saja, mylist1 menjawab 5 pertanyaan tentang panjang, jadi dan mengembalikan mylist2. Dan itu saja. Ini tidak ada hubungannya dengan elemen mylist1 dan mylist2 - mereka tidak memasukkan gambar di mana pun.Contoh kedua:
&
padalist
Di sisi lain,
&
adalah operator seperti yang lain, seperti+
misalnya. Itu dapat didefinisikan untuk tipe dengan mendefinisikan metode khusus pada kelas itu.int
mendefinisikannya sebagai bitwise "dan", dan bool mendefinisikannya sebagai logis "dan", tetapi itu hanya satu opsi: misalnya, set dan beberapa objek lain seperti tampilan kunci dict mendefinisikannya sebagai persimpangan set.list
tidak mendefinisikannya, mungkin karena Guido tidak memikirkan cara yang jelas untuk mendefinisikannya.numpy
Di sisi lain: -D, array numpy adalah spesial, atau setidaknya mereka berusaha menjadi. Tentu saja, numpy.array hanya sebuah kelas, ia tidak dapat menimpa
and
dengan cara apa pun, sehingga ia melakukan hal terbaik berikutnya: ketika ditanya "apakah Anda benar", numpy.array meningkatkan ValueError, secara efektif mengatakan "tolong ulangi pertanyaannya, saya pandangan kebenaran tidak cocok dengan model Anda ". (Perhatikan bahwa pesan ValueError tidak berbicara tentangand
- karena numpy.array tidak tahu siapa yang menanyakannya; itu hanya berbicara tentang kebenaran.)Sebab
&
, ceritanya sangat berbeda. numpy.array dapat mendefinisikannya seperti yang diinginkan, dan mendefinisikan&
secara konsisten dengan operator lain: pointwise. Jadi Anda akhirnya mendapatkan apa yang Anda inginkan.HTH,
sumber
Operator boolean hubungan pendek (
and
,or
) tidak dapat diganti karena tidak ada cara yang memuaskan untuk melakukan ini tanpa memperkenalkan fitur bahasa baru atau mengorbankan hubungan pendek. Karena Anda mungkin atau mungkin tidak tahu, mereka mengevaluasi operan pertama untuk nilai kebenarannya, dan tergantung pada nilai itu, apakah mengevaluasi dan mengembalikan argumen kedua, atau tidak mengevaluasi argumen kedua dan mengembalikan yang pertama:Perhatikan bahwa (hasil mengevaluasi) operan aktual dikembalikan, bukan nilai kebenarannya.
Satu-satunya cara untuk menyesuaikan perilaku mereka adalah dengan mengganti
__nonzero__
(diubah namanya menjadi__bool__
Python 3), sehingga Anda dapat memengaruhi operan mana yang dikembalikan, tetapi tidak mengembalikan sesuatu yang berbeda. Daftar (dan koleksi lainnya) didefinisikan sebagai "benar" ketika mengandung apa saja, dan "falsey" ketika kosong.Array NumPy menolak gagasan itu: Untuk kasus penggunaan yang mereka tuju, dua gagasan kebenaran yang berbeda adalah umum: (1) Apakah elemen apa pun benar, dan (2) apakah semua elemen itu benar. Karena keduanya benar-benar (dan diam-diam) tidak kompatibel, dan tidak ada yang jelas lebih benar atau lebih umum, NumPy menolak untuk menebak dan mengharuskan Anda untuk secara eksplisit menggunakan
.any()
atau.all()
.&
dan|
(dannot
, omong-omong) dapat sepenuhnya ditimpa, karena mereka tidak mengalami hubungan pendek. Mereka dapat mengembalikan apa saja ketika ditimpa, dan NumPy memanfaatkannya untuk melakukan operasi elemen-bijaksana, seperti yang mereka lakukan dengan hampir semua operasi skalar lainnya. Daftar, di sisi lain, tidak menyiarkan operasi di seluruh elemen mereka. Sama sepertimylist1 - mylist2
tidak berarti apa-apa danmylist1 + mylist2
berarti sesuatu yang sama sekali berbeda, tidak ada&
operator untuk daftar.sumber
[False] or [True]
dievaluasi[False]
, dan[False] and [True]
dievaluasi[True]
.Contoh 1:
Ini adalah bagaimana dan operator.
x dan y => jika x salah, maka x , kalau tidak y
Jadi dengan kata lain, karena
mylist1
tidakFalse
, hasil dari ekspresi adalahmylist2
. (Hanya daftar kosong dievaluasiFalse
.)Contoh 2:
The
&
operator adalah untuk bitwise dan, seperti yang Anda sebutkan. Operasi bitwise hanya bekerja pada angka. Hasil dari a & b adalah angka yang terdiri dari 1s dalam bit yaitu 1 pada a dan b . Sebagai contoh:Lebih mudah untuk melihat apa yang terjadi menggunakan biner literal (angka yang sama seperti di atas):
Operasi bitwise serupa dalam konsepnya dengan operasi boolean (kebenaran), tetapi mereka hanya bekerja pada bit.
Jadi, diberikan beberapa pernyataan tentang mobil saya
Logika "dan" dari kedua pernyataan ini adalah:
Keduanya benar, setidaknya untuk mobil saya. Jadi nilai pernyataan secara keseluruhan adalah logis benar .
Bitwise "dan" dari kedua pernyataan ini sedikit lebih samar:
Jika python tahu bagaimana mengubah pernyataan ke nilai numerik, maka ia akan melakukannya dan menghitung bitwise-dan dari dua nilai. Ini mungkin membuat Anda percaya bahwa
&
itu dapat dipertukarkan denganand
, tetapi seperti pada contoh di atas mereka adalah hal yang berbeda. Juga, untuk objek yang tidak dapat dikonversi, Anda hanya akan mendapatkanTypeError
.Contoh 3 dan 4:
Numpy mengimplementasikan operasi aritmatika untuk array:
Tetapi tidak menerapkan operasi logis untuk array, karena Anda tidak dapat membebani operator logis dengan python . Itu sebabnya contoh tiga tidak berfungsi, tetapi contoh empat tidak.
Jadi untuk menjawab pertanyaan
and
vs Anda&
: Gunakanand
.Operasi bitwise digunakan untuk memeriksa struktur angka (bit mana yang diset, bit mana yang tidak disetel). Informasi semacam ini sebagian besar digunakan dalam antarmuka sistem operasi tingkat rendah ( unix bits bits) ). Sebagian besar program python tidak perlu tahu itu.
Operasi logis (
and
,or
,not
), bagaimanapun, digunakan sepanjang waktu.sumber
Dalam Python ekspresi
X and Y
pengembalianY
, mengingat itubool(X) == True
atau salah satuX
atauY
mengevaluasi ke False, misalnya:Operator bitwise sama sekali tidak ditentukan untuk daftar. Tapi itu didefinisikan untuk bilangan bulat - beroperasi atas representasi biner dari angka-angka. Pertimbangkan 16 (01000) dan 31 (11111):
NumPy bukan seorang paranormal, ia tidak tahu, apakah maksud Anda misalnya
[False, False]
harus sama denganTrue
dalam ekspresi logis. Dalam ini menimpa perilaku Python standar, yaitu: "Setiap koleksi kosonglen(collection) == 0
adalahFalse
".Mungkin perilaku yang diharapkan dari array & operator NumPy.
sumber
Untuk contoh pertama dan berdasarkan pada dokumen Django itu
akan selalu mengembalikan daftar kedua, memang daftar yang tidak kosong dilihat sebagai nilai True untuk Python sehingga python mengembalikan nilai True 'terakhir' sehingga daftar kedua
sumber
Operasi dengan daftar Python beroperasi pada daftar .
list1 and list2
akan memeriksa apakahlist1
kosong, dan kembalilist1
jika ada, danlist2
jika tidak.list1 + list2
akan ditambahkanlist2
kelist1
, sehingga Anda mendapatkan daftar baru denganlen(list1) + len(list2)
elemen.Operator yang hanya masuk akal ketika elemen diterapkan, seperti
&
, meningkatkan aTypeError
, karena operasi elemen-bijaksana tidak didukung tanpa perulangan melalui elemen.Array numpy mendukung operasi elemen-bijaksana .
array1 & array2
akan menghitung bitwise atau untuk setiap elemen yang sesuai diarray1
danarray2
.array1 + array2
akan menghitung jumlah untuk setiap elemen yang sesuai diarray1
danarray2
.Ini tidak berfungsi untuk
and
danor
.array1 and array2
pada dasarnya adalah kependekan dari kode berikut:Untuk ini, Anda perlu definisi yang baik tentang
bool(array1)
. Untuk operasi global seperti yang digunakan pada daftar Python, definisi adalah bahwabool(list) == True
jikalist
tidak kosong, danFalse
jika kosong. Untuk operasi elemen-bijaksana numpy, ada beberapa ketidakjelasan apakah untuk memeriksa apakah elemen mengevaluasiTrue
, atau semua elemen mengevaluasiTrue
. Karena keduanya bisa dibilang benar, numpy tidak menebak dan memunculkanValueError
kapanbool()
(secara tidak langsung) dipanggil pada array.sumber
Pertanyaan bagus. Mirip dengan pengamatan yang Anda miliki tentang contoh 1 dan 4 (atau harus saya katakan 1 & 4 :)) lebih dari operator
and
bitwise logis&
, saya alami padasum
operator. Numpysum
dan pysum
berperilaku berbeda juga. Sebagai contoh:Misalkan "mat" adalah array 2d 5x5 numpy seperti:
Kemudian numpy.sum (mat) memberikan jumlah total dari seluruh matriks. Sedangkan jumlah bawaan dari Python seperti jumlah (tikar) total sepanjang sumbu saja. Lihat di bawah:
sumber