Mengapa tidak ada ++
dan --
operator di Python?
Mengapa tidak ada ++
dan --
operator di Python?
Jawaban:
Itu bukan karena itu tidak masuk akal; masuk akal untuk mendefinisikan "x ++" sebagai "x + = 1, mengevaluasi ke pengikatan x sebelumnya".
Jika Anda ingin mengetahui alasan aslinya, Anda harus mengarungi milis Python lama atau bertanya kepada seseorang yang ada di sana (mis. Guido), tetapi cukup mudah untuk membenarkan setelah fakta:
Peningkatan dan penurunan sederhana tidak diperlukan sebanyak dalam bahasa lain. Anda tidak sering menulis hal-hal seperti for(int i = 0; i < 10; ++i)
di Python; alih-alih Anda melakukan hal-hal seperti for i in range(0, 10)
.
Karena itu tidak diperlukan hampir sesering mungkin, ada jauh lebih sedikit alasan untuk memberikan sintaksisnya sendiri; ketika Anda perlu kenaikan, +=
biasanya baik-baik saja.
Itu bukan keputusan apakah itu masuk akal, atau apakah itu bisa dilakukan - ya, dan itu bisa. Ini pertanyaan apakah manfaatnya layak ditambahkan ke sintaks inti bahasa. Ingat, ini adalah empat operator - postinc, postdec, preinc, predec, dan masing-masing operator perlu memiliki kelas yang berlebih; mereka semua harus ditentukan, dan diuji; itu akan menambahkan opcodes ke bahasa (menyiratkan mesin VM yang lebih besar, dan karena itu lebih lambat); setiap kelas yang mendukung peningkatan logis perlu mengimplementasikannya (di atas +=
dan -=
).
Ini semua berlebihan dengan +=
dan -=
, jadi itu akan menjadi rugi bersih.
i
langsung - jika Anda benar-benar membutuhkannya dan tidak bisa hanya menggunakan misalnyaarray.append()
i++
dan ++i
...
++
dan --
digunakan dengan cara yang menghasilkan tidak ditentukan atau tidak ditentukan tingkah laku. Mereka memungkinkan untuk menulis kode yang rumit, sulit diurai dengan benar.
Jawaban asli yang saya tulis ini adalah mitos dari cerita rakyat komputasi : dibantah oleh Dennis Ritchie sebagai "secara historis tidak mungkin" seperti yang tercantum dalam surat kepada editor Komunikasi ACM Juli 2012 doi: 10.1145 / 2209249.2209251
Operator kenaikan / penurunan C ditemukan pada saat ketika kompiler C tidak terlalu pintar dan penulis ingin dapat menentukan maksud langsung bahwa operator bahasa mesin harus digunakan yang menyimpan beberapa siklus untuk kompiler yang mungkin melakukan a
load memory
load 1
add
store memory
dari pada
inc memory
dan PDP-11 bahkan didukung "autoincrement" dan "autoincrement ditangguhkan" petunjuk sesuai dengan *++p
dan *p++
masing-masing. Lihat bagian 5.3 manual jika penasaran.
Karena kompiler cukup pintar untuk menangani trik optimasi tingkat tinggi yang dibangun ke dalam sintaks C, mereka hanyalah kenyamanan sintaksis sekarang.
Python tidak memiliki trik untuk menyampaikan maksud kepada assembler karena tidak menggunakannya.
Saya selalu menganggap itu ada hubungannya dengan baris zen dari python ini:
Seharusnya ada satu - dan lebih disukai hanya satu - cara yang jelas untuk melakukannya.
x ++ dan x + = 1 melakukan hal yang persis sama, jadi tidak ada alasan untuk memiliki keduanya.
one--
adalah nol?
one--
adalah satu dalam kalimat, tetapi nol segera setelahnya. Jadi 'koan' ini juga mengisyaratkan bahwa operator kenaikan / penurunan tidak jelas.
Tentu saja, kita dapat mengatakan "Guido baru saja memutuskan seperti itu", tetapi saya pikir pertanyaannya adalah tentang alasan keputusan itu. Saya pikir ada beberapa alasan:
Karena, dalam Python, integer tidak dapat diubah (int's + = sebenarnya mengembalikan objek yang berbeda).
Juga, dengan ++ / - Anda perlu khawatir tentang sebelum / sesudah kenaikan / penurunan, dan hanya perlu satu tombol lagi untuk menulis x+=1
. Dengan kata lain, itu menghindari potensi kebingungan dengan mengorbankan sangat sedikit keuntungan.
42++
... Sesuatu seperti ini (memodifikasi konstan literal) itu benar-benar mungkin dalam beberapa kompiler Fortran lama (atau jadi saya sudah membaca): Semua penggunaan masa depan dari literal dalam menjalankan program maka akan benar-benar memiliki nilai yang berbeda. Selamat men-debug!
int
secara umum tidak dapat diubah. Sebuah int
di C hanya menunjukkan tempat di memori. Dan bit di tempat itu sangat bisa berubah. Anda dapat, misalnya, membuat referensi dari int
dan mengubah referensi dari referensi itu. Perubahan ini terlihat di semua referensi (termasuk int
variabel asli ) ke tempat itu. Hal yang sama tidak berlaku untuk objek integer Python.
Python banyak tentang kejelasan dan tidak ada programmer yang mungkin menebak dengan benar arti --a
kecuali dia belajar bahasa yang memiliki konstruksi itu.
Python juga banyak tentang menghindari konstruksi yang mengundang kesalahan dan ++
operator dikenal sebagai sumber cacat yang kaya. Dua alasan ini cukup untuk tidak memiliki operator di Python.
Keputusan bahwa Python menggunakan lekukan untuk menandai blok daripada cara sintaksis seperti beberapa bentuk bracketing mulai / akhir atau penandaan akhir wajib sebagian besar didasarkan pada pertimbangan yang sama.
Untuk ilustrasi, kita lihat di diskusi sekitar memperkenalkan operator kondisional (di C: cond ? resultif : resultelse
) ke Python pada tahun 2005. Baca setidaknya pesan pertama dan pesan keputusan itu diskusi (yang memiliki beberapa prekursor pada topik yang sama sebelumnya).
Trivia: PEP yang sering disebutkan di sini adalah "Python Extension Proposal" PEP 308 . LC berarti pemahaman daftar , GE berarti ekspresi generator (dan jangan khawatir jika itu membingungkan Anda, mereka bukan satu-satunya dari beberapa titik rumit Python).
Pemahaman saya tentang mengapa python tidak memiliki ++
operator adalah sebagai berikut: Ketika Anda menulis ini dengan python a=b=c=1
Anda akan mendapatkan tiga variabel (label) menunjuk pada objek yang sama (yang nilainya 1). Anda dapat memverifikasi ini dengan menggunakan fungsi id yang akan mengembalikan alamat memori objek:
In [19]: id(a)
Out[19]: 34019256
In [20]: id(b)
Out[20]: 34019256
In [21]: id(c)
Out[21]: 34019256
Ketiga variabel (label) menunjuk ke objek yang sama. Sekarang tambahkan salah satu variabel dan lihat bagaimana hal itu memengaruhi alamat memori:
In [22] a = a + 1
In [23]: id(a)
Out[23]: 34019232
In [24]: id(b)
Out[24]: 34019256
In [25]: id(c)
Out[25]: 34019256
Anda dapat melihat variabel itu a
sekarang menunjuk ke objek lain sebagai variabel b
dan c
. Karena Anda telah menggunakannya a = a + 1
jelas secara eksplisit. Dengan kata lain Anda menetapkan sepenuhnya objek lain untuk diberi label a
. Bayangkan bahwa Anda dapat menulis a++
itu akan menyarankan bahwa Anda tidak menugaskan objek variabel a
baru tetapi kenaikan ratter yang lama. Semua ini adalah IMHO untuk meminimalkan kebingungan. Untuk pemahaman yang lebih baik, lihat cara kerja variabel python:
Apakah Python call-by-value atau call-by-reference? Tidak juga.
Apakah Python melewati nilai, atau dengan referensi?
Apakah Python pass-by-reference atau pass-by-value?
Python: Bagaimana cara saya melewatkan variabel dengan referensi?
Memahami variabel Python dan Manajemen Memori
Meniru perilaku pass-by-value dalam python
Itu hanya dirancang seperti itu. Operator kenaikan dan penurunan hanyalah jalan pintas untuk x = x + 1
. Python biasanya mengadopsi strategi desain yang mengurangi jumlah cara alternatif melakukan operasi. Penugasan augmented adalah hal yang paling dekat dengan operator increment / decrement di Python, dan mereka bahkan tidak ditambahkan hingga Python 2.0.
return a[i++]
dengan return a[i=i+1]
.
Saya sangat baru untuk python tapi saya menduga alasannya adalah karena penekanan antara objek yang bisa berubah dan tidak berubah dalam bahasa. Sekarang, saya tahu bahwa x ++ dapat dengan mudah diartikan sebagai x = x +1, tetapi sepertinya Anda menambahkan di tempat objek yang bisa berubah.
Hanya dugaan / perasaan / dugaan saya.
x++
lebih dekat x += 1
daripada daripada x = x + 1
, keduanya membuat perbedaan juga pada objek yang bisa berubah.
Pertama, Python hanya secara tidak langsung dipengaruhi oleh C; itu sangat dipengaruhi oleh ABC , yang tampaknya tidak memiliki operator ini , jadi seharusnya tidak menjadi kejutan besar untuk tidak menemukannya di Python juga.
Kedua, seperti yang dikatakan orang lain, kenaikan dan penurunan didukung oleh +=
dan -=
sudah.
Ketiga, dukungan penuh untuk ++
dan --
set operator biasanya mencakup mendukung versi awalan dan postfix mereka. Dalam C dan C ++, ini dapat menyebabkan semua jenis konstruksi "indah" yang tampaknya (bagi saya) bertentangan dengan semangat kesederhanaan dan keterusterangan yang dianut oleh Python.
Misalnya, sementara pernyataan C while(*t++ = *s++);
mungkin tampak sederhana dan elegan untuk programmer yang berpengalaman, bagi seseorang yang mempelajarinya, itu sama sekali tidak sederhana. Lemparkan campuran kenaikan dan penurunan awalan dan postfix, dan bahkan banyak pro harus berhenti dan berpikir sedikit.
Saya percaya ini berasal dari pernyataan Python bahwa "eksplisit lebih baik daripada implisit".
Ini mungkin karena @GlennMaynard melihat masalah ini dibandingkan dengan bahasa lain, tetapi dengan Python, Anda melakukan berbagai hal dengan cara python. Itu bukan pertanyaan 'mengapa'. Itu ada di sana dan Anda dapat melakukan hal-hal dengan efek yang sama x+=
. Dalam The Zen of Python , diberikan: "seharusnya hanya ada satu cara untuk menyelesaikan masalah." Pilihan ganda sangat bagus dalam seni (kebebasan berekspresi) tetapi buruk dalam rekayasa.
The ++
kelas operator adalah ekspresi dengan efek samping. Ini adalah sesuatu yang umumnya tidak ditemukan dengan Python.
Untuk alasan yang sama tugas bukanlah ekspresi dalam Python, sehingga mencegah if (a = f(...)) { /* using a here */ }
idiom umum .
Terakhir saya curiga ada operator yang tidak terlalu konsisten dengan semantik referensi Python. Ingat, Python tidak memiliki variabel (atau pointer) dengan semantik yang diketahui dari C / C ++.
f(a)
mana a
daftar, beberapa objek yang tidak dapat diubah.
Mungkin pertanyaan yang lebih baik adalah untuk bertanya mengapa operator ini ada di C. K&R menyebut operator kenaikan dan penurunan 'tidak biasa' (Bagian 2.8 halaman 46). Pendahuluan menyebut mereka 'lebih ringkas dan sering lebih efisien'. Saya menduga bahwa fakta bahwa operasi ini selalu muncul dalam manipulasi pointer juga telah berperan dalam pengantar mereka. Dalam Python mungkin telah diputuskan bahwa tidak masuk akal untuk mencoba mengoptimalkan peningkatan (pada kenyataannya saya hanya melakukan tes dalam C, dan tampaknya bahwa rakitan yang dihasilkan gcc menggunakan addl bukan incl dalam kedua kasus) dan tidak ada pointer aritmatika; jadi itu akan menjadi Satu Lagi Cara untuk Melakukannya dan kita tahu Python benci itu.
seperti yang saya mengerti sehingga Anda tidak akan berpikir nilai dalam memori berubah. di c ketika Anda melakukan x ++ nilai x dalam memori berubah. tetapi dalam python semua angka tidak dapat diubah maka alamat yang x menunjuk sebagai masih memiliki x bukan x +1. ketika Anda menulis x ++ Anda akan berpikir bahwa x mengubah apa yang sebenarnya terjadi adalah bahwa x refrence diubah ke lokasi di memori di mana x +1 disimpan atau menciptakan kembali lokasi ini jika tidak ada.
++
berbeda dari ini += 1
?
Untuk melengkapi jawaban yang sudah bagus di halaman itu:
Misalkan kita memutuskan untuk melakukan ini, awalan ( ++i
) yang akan merusak operator + dan - unary.
Hari ini, awalan dengan ++
atau --
tidak melakukan apa-apa, karena memungkinkan unary plus operator dua kali (tidak melakukan apa-apa) atau unary minus dua kali (dua kali: membatalkan sendiri)
>>> i=12
>>> ++i
12
>>> --i
12
Sehingga berpotensi mematahkan logika itu.
Jawaban lain telah menjelaskan mengapa itu tidak diperlukan untuk iterator, tetapi kadang-kadang berguna ketika menugaskan untuk meningkatkan variabel in-line, Anda dapat mencapai efek yang sama menggunakan tupel dan penugasan ganda:
b = ++a
menjadi:
a,b = (a+1,)*2
dan b = a++
menjadi:
a,b = a+1, a
Python 3.8 memperkenalkan tugas :=
operator, memungkinkan kita untuk mencapai foo(++a)
dengan
foo(a:=a+1)
foo(a++)
masih sulit dipahami.
Saya pikir ini berkaitan dengan konsep mutabilitas dan kekekalan objek. 2,3,4,5 tidak berubah dalam python. Lihat gambar di bawah ini. 2 telah memperbaiki id hingga proses python ini.
x ++ pada dasarnya berarti peningkatan di tempat seperti C. Dalam C, x ++ melakukan peningkatan di tempat. Jadi, x = 3, dan x ++ akan menambah 3 di memori menjadi 4, tidak seperti python di mana 3 akan tetap ada di memori.
Jadi dengan python, Anda tidak perlu membuat ulang nilai dalam memori. Ini dapat menyebabkan optimalisasi kinerja.
Ini adalah jawaban berdasarkan firasat.
Saya tahu ini adalah utas lama, tetapi kasus penggunaan yang paling umum untuk ++ i tidak tercakup, yaitu menjadi pengindeksan secara manual saat tidak ada indeks yang disediakan. Situasi ini adalah mengapa python menyediakan enumerate ()
Contoh: Dalam bahasa apa pun, ketika Anda menggunakan konstruksi seperti foreach untuk beralih pada set - demi contoh, kami bahkan akan mengatakan itu set unordered dan Anda perlu indeks unik untuk semuanya untuk membedakan mereka, katakan
i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
uniquestuff[key] = '{0}{1}'.format(val, i)
i += 1
Dalam kasus seperti ini, python menyediakan metode enumerasi, misalnya
for i, (key, val) in enumerate(stuff.items()) :