Saya tahu Ruby dengan sangat baik. Saya percaya bahwa saya mungkin perlu mempelajari Python saat ini. Bagi mereka yang tahu keduanya, konsep apa yang sama antara keduanya, dan apa yang berbeda?
Saya mencari daftar yang mirip dengan primer yang saya tulis untuk Learning Lua for JavaScripters : hal-hal sederhana seperti signifikansi spasi putih dan konstruksi perulangan; nama nil
dalam Python, dan nilai apa yang dianggap "benar"; Apakah idiom untuk menggunakan yang setara dengan map
dan each
, atau menggumamkan sesuatu tentang daftar pemahaman yang menggumamkan norma?
Jika saya mendapatkan beragam jawaban yang baik, saya senang menggabungkannya ke dalam wiki komunitas. Atau Anda semua dapat saling bertarung dan tidur untuk mencoba membuat daftar lengkap yang benar.
Sunting : Agar jelas, tujuan saya adalah "layak" dan idiom Python. Jika ada yang setara dengan Python inject
, tetapi tidak ada yang menggunakannya karena ada cara yang lebih baik / berbeda untuk mencapai fungsi umum dari iterasi daftar dan mengumpulkan hasil di sepanjang jalan, saya ingin tahu bagaimana Anda melakukan sesuatu. Mungkin saya akan memperbarui pertanyaan ini dengan daftar tujuan umum, bagaimana Anda mencapainya di Ruby, dan bertanya apa yang setara di Python.
Jawaban:
Inilah beberapa perbedaan utama bagi saya:
Ruby memiliki blok; Python tidak.
Python memiliki fungsi; Ruby tidak. Dengan Python, Anda bisa mengambil fungsi atau metode apa saja dan meneruskannya ke fungsi lain. Di Ruby, semuanya adalah metode, dan metode tidak dapat diteruskan secara langsung. Sebagai gantinya, Anda harus membungkusnya dengan Proc untuk melewatinya.
Ruby dan Python keduanya mendukung penutupan, tetapi dengan cara yang berbeda. Dengan Python, Anda bisa mendefinisikan fungsi di dalam fungsi lain. Fungsi dalam memiliki akses baca ke variabel dari fungsi luar, tetapi tidak akses tulis. Di Ruby, Anda menentukan penutupan menggunakan blok. Penutupan memiliki akses baca dan tulis penuh ke variabel dari lingkup luar.
Python memiliki daftar pemahaman, yang cukup ekspresif. Misalnya, jika Anda memiliki daftar angka, Anda dapat menulis
untuk mendapatkan daftar kuadrat baru dari semua nilai yang lebih besar dari 15. Di Ruby, Anda harus menulis yang berikut:
Kode Ruby tidak terasa kompak. Ini juga tidak seefisien karena pertama-tama mengubah array nilai menjadi array menengah yang lebih pendek yang mengandung nilai lebih besar dari 15. Kemudian, dibutuhkan array perantara dan menghasilkan array akhir yang berisi kotak-kotak perantara. Array perantara kemudian dibuang. Jadi, Ruby berakhir dengan 3 array dalam memori selama perhitungan; Python hanya membutuhkan daftar input dan daftar yang dihasilkan.
Python juga menyediakan pemahaman peta yang serupa.
Python mendukung tuple; Ruby tidak. Di Ruby, Anda harus menggunakan array untuk mensimulasikan tupel.
Ruby mendukung pernyataan switch / case; Python tidak.
Ruby mendukungexpr ? val1 : val2
operator ternary standar ; Python tidak.Ruby hanya mendukung satu warisan. Jika Anda perlu meniru banyak pewarisan, Anda dapat mendefinisikan modul dan menggunakan campuran untuk menarik metode modul ke dalam kelas. Python mendukung multiple inheritance daripada module mix-in.
Python hanya mendukung fungsi lambda satu baris. Blok Ruby, yang merupakan jenis / semacam fungsi lambda, bisa sangat besar. Karena itu, kode Ruby biasanya ditulis dalam gaya yang lebih fungsional daripada kode Python. Misalnya, untuk mengulang daftar di Ruby, biasanya Anda lakukan
Blok bekerja sangat mirip dengan fungsi yang diteruskan
collection.each
. Jika Anda melakukan hal yang sama dengan Python, Anda harus mendefinisikan fungsi dalam bernama dan kemudian meneruskannya ke kumpulan setiap metode (jika daftar mendukung metode ini):Itu tidak mengalir dengan sangat baik. Jadi, biasanya pendekatan non-fungsional berikut akan digunakan dalam Python:
Menggunakan sumber daya dengan cara yang aman sangat berbeda antara kedua bahasa. Di sini, masalahnya adalah Anda ingin mengalokasikan beberapa sumber daya (membuka file, mendapatkan kursor database, dll), melakukan beberapa operasi sewenang-wenang di atasnya, dan kemudian menutupnya dengan cara yang aman bahkan jika pengecualian terjadi.
Di Ruby, karena blok sangat mudah digunakan (lihat # 9), Anda biasanya akan mengkode pola ini sebagai metode yang mengambil blok untuk operasi sewenang-wenang untuk dilakukan pada sumber daya.
Dalam Python, mengirimkan fungsi untuk tindakan arbitrer sedikit clunkier karena Anda harus menulis nama, fungsi bagian dalam (lihat # 9). Sebagai gantinya, Python menggunakan
with
pernyataan untuk penanganan sumber daya yang aman. Lihat Bagaimana cara membersihkan objek Python dengan benar? untuk lebih jelasnya.sumber
nonlocal
memperbaiki ini 4. Python juga memberi Anda ekspresi generator (mirip dengan pemahaman daftar, tetapi jangan menghitung apa pun sampai diminta untuk - menganggap daftar pemahaman sebagai ekspresi generator yang diumpankan kelist
(yang mengambil iterable dan mengembalikan daftar yang berisi segalanya) iterable yang dihasilkan) - ini dapat menghemat banyak usaha dalam beberapa kasus).val1 if expr else val2
. 8. Meskipun saya melihatnya sebagian besar digunakan untuk augmentasi gaya mixin.values.map{|v| v*v if v > 15}.compact
. IMHO, ini bahkan lebih ekspresif (dan tentunya lebih jelas) daripada contoh python Anda.values.map{|v| v*v if v > 15}.compact!
. Ini berarti bahwa hanya daftar input dan daftar yang dihasilkan yang ada di memori. Lihat # 4 di sini: igvita.com/2008/07/08/6-optimisasi-tips-for-ruby-mriSaya baru saja menghabiskan beberapa bulan belajar Python setelah 6 tahun Ruby. Benar-benar tidak ada perbandingan yang bagus untuk kedua bahasa itu, jadi saya memutuskan untuk membuat dan menulis sendiri. Sekarang, ini terutama berkaitan dengan pemrograman fungsional, tetapi karena Anda menyebutkan
inject
metode Ruby , saya kira kita berada pada gelombang yang sama.Saya harap ini membantu: 'Keburukan' Python
Beberapa poin yang akan membuat Anda bergerak ke arah yang benar:
Semua kebaikan pemrograman fungsional yang Anda gunakan di Ruby adalah dalam Python, dan itu bahkan lebih mudah. Misalnya, Anda dapat memetakan fungsi persis seperti yang Anda harapkan:
Python tidak memiliki metode yang bertingkah seperti
each
. Karena Anda hanya menggunakaneach
untuk efek samping, ekuivalen dalam Python adalah untuk loop:Pemahaman daftar sangat bagus ketika a) Anda harus berurusan dengan fungsi dan koleksi objek bersama-sama dan b) ketika Anda perlu beralih menggunakan beberapa indeks. Misalnya, untuk menemukan semua palindrom dalam string (dengan asumsi Anda memiliki fungsi
p()
yang mengembalikan true untuk palindrom), yang Anda butuhkan hanyalah pemahaman daftar tunggal:sumber
Class.method
, metode ini "tidak terikat" dan argumen pertama harus berupaClass
instance; ketika Anda menulisobject.method
, metode ini "terikat" keobject
instance dariClass
. Ini memungkinkan Anda memilih apakah akan menggunakan peta (dll) untuk memanggil metode pada instance perbedaan setiap kali (lulus metode tidak terikat), atau untuk menjaga instance tetap dan meneruskan argumen kedua yang berbeda setiap kali. Keduanya bermanfaat.[s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]
- baris ini menunjukkan betapa sulitnya Python membaca. Ketika Anda membaca kode Ruby, Anda menggerakkan mata Anda dari kiri ke kanan, tanpa pengembalian. Tetapi untuk membaca kode Python, Anda harus ke kiri-kanan-kiri-kanan-kanan-kiri ... dan tanda kurung, tanda kurung, tanda kurung, tanda kurung ... Juga dalam Python Anda sering perlu mencampur metode dan fungsi. Kegilaan:E(C(A.B()).D())
bukan RubyA.B.C.D.E
Saran saya: Jangan mencoba mempelajari perbedaannya. Pelajari cara mendekati masalah dengan Python. Sama seperti ada pendekatan Ruby untuk setiap masalah (yang bekerja dengan sangat baik memberikan keterbatasan dan kekuatan bahasa), ada pendekatan Python untuk masalah tersebut. keduanya berbeda. Untuk mendapatkan yang terbaik dari setiap bahasa, Anda harus benar-benar mempelajari bahasa itu sendiri, dan bukan hanya "terjemahan" dari satu ke yang lain.
Sekarang, dengan itu, perbedaannya akan membantu Anda beradaptasi lebih cepat dan membuat 1 dari modifikasi ke program Python. Dan itu bagus untuk memulai menulis. Tetapi cobalah belajar dari proyek lain mengapa di balik arsitektur dan keputusan desain daripada bagaimana di balik semantik bahasa ...
sumber
each
metode Ruby ?" Saya bertanya, "Bagaimana hal dilakukan dengan benar di Python berbeda dari Ruby, dan di mana mereka dilakukan dengan benar sama?" Jika Pythonfalse
sebenarnyaFalse
, itu sama pentingnya untuk mengetahui di mana dan kapan aku harus melakukan sesuatu dengan cara Rubyesque, dan di mana dan kapan aku tidak boleh.Saya tahu sedikit Ruby, tetapi di sini ada beberapa poin tentang hal-hal yang Anda sebutkan:
nil
, nilai yang mengindikasikan kurangnya nilai, akan menjadiNone
(perhatikan bahwa Anda memeriksanya sepertix is None
ataux is not None
, tidak dengan==
- atau dengan paksaan ke boolean, lihat poin berikutnya).None
, Nomor nol-esque (0
,0.0
,0j
(bilangan kompleks)) dan koleksi kosong ([]
,{}
,set()
, string kosong""
, dll) dianggap falsy, segala sesuatu yang lain dianggap truthy.for
-) loop secara eksplisit. Untuk menghasilkan banyak barang baru tanpa efek samping, gunakan daftar pemahaman (atau kerabat mereka - ekspresi generator untuk iterator satu kali malas, dikt / set pemahaman untuk koleksi tersebut).Mengenai perulangan: Anda miliki
for
, yang beroperasi pada iterable (! No menghitung), danwhile
, yang melakukan apa yang Anda harapkan. Fromer jauh lebih kuat, berkat dukungan luas untuk iterator. Bukan hanya hampir semua yang bisa menjadi iterator, bukan daftar adalah iterator (setidaknya dalam Python 3 - dalam Python 2, Anda memiliki keduanya dan defaultnya adalah list, sayangnya). Ada banyak alat untuk bekerja dengan iterator -zip
iterates sejumlah iterables secara paralel,enumerate
memberi Anda(index, item)
(pada setiap iterable, bukan hanya pada daftar), bahkan mengiris iterables iterables (mungkin besar atau tak terbatas)! Saya menemukan bahwa ini membuat banyak tugas pengulangan jauh lebih sederhana. Tidak perlu dikatakan, mereka mengintegrasikan dengan baik dengan daftar pemahaman, ekspresi generator, dll.sumber
x is None
ataux is not None
? Saya selalu mengecek denganx == None
danx != None
.x
mendefinisikan__eq__
dengan cara konyol, itu bisa memberikan positif palsu. Jika__eq__
tidak diprogram dengan cukup hati-hati, itu bisa macet (misalnyaAttributeError
) ketika diberi nilai-nilai tertentu (yaituNone
). Sebaliknya,is
tidak dapat ditimpa - selalu membandingkan identitas objek, yang merupakan cara yang tepat (paling kuat, paling sederhana dan paling bersih) untuk memeriksa singleton.Di Ruby, variabel instan dan metode sama sekali tidak terkait, kecuali ketika Anda secara eksplisit menghubungkannya dengan attr_accessor atau sesuatu seperti itu.
Dalam Python, metode hanyalah kelas atribut khusus: satu yang dapat dieksekusi.
Jadi misalnya:
Perbedaan itu memiliki banyak implikasi, seperti misalnya yang merujuk ke fx merujuk pada objek metode, daripada memanggilnya. Juga, seperti yang Anda lihat, fx bersifat publik secara default, sedangkan di Ruby, variabel instan bersifat pribadi secara default.
sumber