Perhatikan ungkapan berikut. Perhatikan bahwa beberapa ekspresi diulang untuk menampilkan "konteks".
(ini adalah daftar yang panjang)
a, b = 1, 2 # simple sequence assignment
a, b = ['green', 'blue'] # list asqignment
a, b = 'XY' # string assignment
a, b = range(1,5,2) # any iterable will do
# nested sequence assignment
(a,b), c = "XY", "Z" # a = 'X', b = 'Y', c = 'Z'
(a,b), c = "XYZ" # ERROR -- too many values to unpack
(a,b), c = "XY" # ERROR -- need more than 1 value to unpack
(a,b), c, = [1,2],'this' # a = '1', b = '2', c = 'this'
(a,b), (c,) = [1,2],'this' # ERROR -- too many values to unpack
# extended sequence unpacking
a, *b = 1,2,3,4,5 # a = 1, b = [2,3,4,5]
*a, b = 1,2,3,4,5 # a = [1,2,3,4], b = 5
a, *b, c = 1,2,3,4,5 # a = 1, b = [2,3,4], c = 5
a, *b = 'X' # a = 'X', b = []
*a, b = 'X' # a = [], b = 'X'
a, *b, c = "XY" # a = 'X', b = [], c = 'Y'
a, *b, c = "X...Y" # a = 'X', b = ['.','.','.'], c = 'Y'
a, b, *c = 1,2,3 # a = 1, b = 2, c = [3]
a, b, c, *d = 1,2,3 # a = 1, b = 2, c = 3, d = []
a, *b, c, *d = 1,2,3,4,5 # ERROR -- two starred expressions in assignment
(a,b), c = [1,2],'this' # a = '1', b = '2', c = 'this'
(a,b), *c = [1,2],'this' # a = '1', b = '2', c = ['this']
(a,b), c, *d = [1,2],'this' # a = '1', b = '2', c = 'this', d = []
(a,b), *c, d = [1,2],'this' # a = '1', b = '2', c = [], d = 'this'
(a,b), (c, *d) = [1,2],'this' # a = '1', b = '2', c = 't', d = ['h', 'i', 's']
*a = 1 # ERROR -- target must be in a list or tuple
*a = (1,2) # ERROR -- target must be in a list or tuple
*a, = (1,2) # a = [1,2]
*a, = 1 # ERROR -- 'int' object is not iterable
*a, = [1] # a = [1]
*a = [1] # ERROR -- target must be in a list or tuple
*a, = (1,) # a = [1]
*a, = (1) # ERROR -- 'int' object is not iterable
*a, b = [1] # a = [], b = 1
*a, b = (1,) # a = [], b = 1
(a,b),c = 1,2,3 # ERROR -- too many values to unpack
(a,b), *c = 1,2,3 # ERROR - 'int' object is not iterable
(a,b), *c = 'XY', 2, 3 # a = 'X', b = 'Y', c = [2,3]
# extended sequence unpacking -- NESTED
(a,b),c = 1,2,3 # ERROR -- too many values to unpack
*(a,b), c = 1,2,3 # a = 1, b = 2, c = 3
*(a,b) = 1,2 # ERROR -- target must be in a list or tuple
*(a,b), = 1,2 # a = 1, b = 2
*(a,b) = 'XY' # ERROR -- target must be in a list or tuple
*(a,b), = 'XY' # a = 'X', b = 'Y'
*(a, b) = 'this' # ERROR -- target must be in a list or tuple
*(a, b), = 'this' # ERROR -- too many values to unpack
*(a, *b), = 'this' # a = 't', b = ['h', 'i', 's']
*(a, *b), c = 'this' # a = 't', b = ['h', 'i'], c = 's'
*(a,*b), = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5, 6, 7]
*(a,*b), *c = 1,2,3,3,4,5,6,7 # ERROR -- two starred expressions in assignment
*(a,*b), (*c,) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), c = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7
*(a,*b), (*c,) = 1,2,3,4,5,'XY' # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y']
*(a,*b), c, d = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7
*(a,*b), (c, d) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), (*c, d) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), *(c, d) = 1,2,3,3,4,5,6,7 # ERROR -- two starred expressions in assignment
*(a,b), c = 'XY', 3 # ERROR -- need more than 1 value to unpack
*(*a,b), c = 'XY', 3 # a = [], b = 'XY', c = 3
(a,b), c = 'XY', 3 # a = 'X', b = 'Y', c = 3
*(a,b), c = 'XY', 3, 4 # a = 'XY', b = 3, c = 4
*(*a,b), c = 'XY', 3, 4 # a = ['XY'], b = 3, c = 4
(a,b), c = 'XY', 3, 4 # ERROR -- too many values to unpack
Bagaimana cara menyimpulkan dengan benar hasil ekspresi seperti itu dengan tangan?
a, *b = 1, 2, 3
jenis membongkar. Tapi ini Py3k kan?Jawaban:
Saya minta maaf untuk panjangnya posting ini, tetapi saya memutuskan untuk memilih kelengkapan.
Setelah Anda mengetahui beberapa aturan dasar, tidaklah sulit untuk menggeneralisasikannya. Saya akan melakukan yang terbaik untuk menjelaskan dengan beberapa contoh. Karena Anda berbicara tentang mengevaluasi ini "dengan tangan", saya akan menyarankan beberapa aturan substitusi sederhana. Pada dasarnya, Anda mungkin akan lebih mudah memahami ekspresi jika semua iterabel diformat dengan cara yang sama.
Untuk tujuan membongkar saja, substitusi berikut ini berlaku di sisi kanan
=
(yaitu untuk nilai r ):Jika Anda menemukan bahwa nilai tidak dapat dibuka, Anda akan membatalkan substitusi. (Lihat di bawah untuk penjelasan lebih lanjut.)
Selain itu, saat Anda melihat koma "polos", anggaplah ada tupel tingkat atas. Lakukan ini di sisi kiri dan kanan (yaitu untuk lvalues dan rvalues ):
Dengan mengingat aturan sederhana tersebut, berikut beberapa contohnya:
Menerapkan aturan di atas, kami mengonversi
"XY"
ke('X', 'Y')
, dan menutupi tanda koma dalam tanda kurung:Korespondensi visual di sini memperjelas cara kerja tugas.
Inilah contoh yang salah:
Mengikuti aturan substitusi di atas, kami mendapatkan yang di bawah ini:
Ini jelas salah; struktur bersarang tidak cocok. Sekarang mari kita lihat cara kerjanya untuk contoh yang sedikit lebih kompleks:
Menerapkan aturan di atas, kami mengerti
Tapi sekarang sudah jelas dari struktur yang
'this'
tidak akan dibongkar, tapi ditugaskan langsung kec
. Jadi kami membatalkan pergantian.Sekarang mari kita lihat apa yang terjadi saat kita membungkus
c
tupel:Menjadi
Sekali lagi, kesalahannya jelas.
c
bukan lagi variabel polos, tetapi variabel di dalam suatu urutan, sehingga urutan yang sesuai di sebelah kanan akan diuraikan(c,)
. Tetapi urutannya memiliki panjang yang berbeda, jadi ada kesalahan.Sekarang untuk pembongkaran diperpanjang menggunakan
*
operator. Ini sedikit lebih rumit, tetapi masih cukup mudah. Variabel yang diawali dengan*
menjadi daftar, yang berisi item apa pun dari urutan terkait yang tidak ditetapkan ke nama variabel. Dimulai dengan contoh yang cukup sederhana:Ini menjadi
Cara termudah untuk menganalisis ini adalah bekerja dari ujung.
'X'
ditugaskan kea
dan'Y'
ditugaskan kec
. Nilai yang tersisa dalam urutan dimasukkan ke dalam daftar dan ditetapkan keb
.Nilai-nilai seperti
(*a, b)
dan(a, *b)
hanyalah kasus khusus di atas. Anda tidak dapat memiliki dua*
operator dalam satu urutan lvalue karena akan menjadi ambigu. Kemana nilai-nilai itu masuk ke dalam sesuatu seperti ini(a, *b, *c, d)
- dalamb
atauc
? Saya akan mempertimbangkan kasus bersarang sebentar lagi.Di sini kesalahannya cukup jelas. Target (
*a
) harus dalam tupel.Ini berfungsi karena ada koma telanjang. Menerapkan aturan ...
Karena tidak ada variabel selain
*a
,*a
slurps semua nilai dalam urutan rvalue. Bagaimana jika Anda mengganti(1, 2)
dengan satu nilai?menjadi
Sekali lagi, kesalahan di sini sudah cukup jelas. Anda tidak dapat membongkar sesuatu yang bukan berurutan, dan
*a
membutuhkan sesuatu untuk dibuka. Jadi kami menyusunnya secara berurutanYang setara dengan
Akhirnya, ini adalah titik kebingungan yang umum:
(1)
sama dengan1
- Anda memerlukan koma untuk membedakan tupel dari pernyataan aritmatika.Sekarang untuk bersarang. Sebenarnya contoh ini tidak ada di bagian "NESTED" Anda; mungkin Anda tidak menyadari itu bersarang?
Menjadi
Nilai pertama di tupel tingkat atas ditugaskan, dan nilai yang tersisa di tupel tingkat atas (
2
dan3
) ditetapkan kec
- seperti yang kita harapkan.Saya sudah menjelaskan di atas mengapa baris pertama menimbulkan kesalahan. Baris kedua konyol tapi inilah mengapa berhasil:
Seperti yang telah dijelaskan sebelumnya, kami bekerja dari ujung.
3
ditetapkan kec
, dan kemudian nilai yang tersisa ditetapkan ke variabel dengan*
sebelumnya, dalam hal ini(a, b)
,. Jadi itu setara dengan(a, b) = (1, 2)
, yang kebetulan berhasil karena ada jumlah elemen yang tepat. Saya tidak dapat memikirkan alasan apa pun ini akan muncul dalam kode kerja. Demikian pula,menjadi
Bekerja dari ujung,
's'
ditugaskan kec
, dan('t', 'h', 'i')
ditugaskan ke(a, *b)
. Bekerja lagi dari akhir,'t'
ditugaskan kea
, dan('h', 'i')
ditugaskan ke b sebagai daftar. Ini adalah contoh konyol lain yang seharusnya tidak pernah muncul dalam kode kerja.sumber
Saya menemukan tupel Python 2 membongkar cukup mudah. Setiap nama di sebelah kiri sesuai dengan seluruh urutan atau satu item dalam urutan di sebelah kanan. Jika nama sesuai dengan satu item dalam urutan apa pun, maka harus ada cukup nama untuk mencakup semua item.
Pembongkaran yang lama, bagaimanapun, tentu bisa membingungkan, karena sangat kuat. Kenyataannya adalah Anda tidak boleh melakukan 10 atau lebih contoh valid terakhir yang Anda berikan - jika datanya terstruktur, itu harus dalam
dict
contoh kelas, bukan formulir tidak terstruktur seperti daftar.Jelas, sintaks baru dapat disalahgunakan. Jawaban atas pertanyaan Anda adalah Anda tidak perlu membaca ekspresi seperti itu - itu praktik yang buruk dan saya ragu ekspresi itu akan digunakan.
Hanya karena Anda dapat menulis ekspresi kompleks yang sewenang-wenang, bukan berarti Anda harus melakukannya. Anda bisa menulis kode seperti
map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables))
tetapi Anda tidak .sumber
Saya pikir kode Anda mungkin menyesatkan, gunakan bentuk lain untuk mengekspresikannya.
Ini seperti menggunakan tanda kurung ekstra dalam ekspresi untuk menghindari pertanyaan tentang prioritas operator. Itu selalu merupakan investasi yang bagus untuk membuat kode Anda dapat dibaca.
Saya lebih suka menggunakan unpacking hanya untuk tugas-tugas sederhana seperti swap.
sumber