Ini selalu membingungkan saya. Sepertinya ini akan lebih baik:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
Dari ini:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
Apakah ada alasan khusus seperti ini?
-
nyatakan bahwa Anda bergabung dengan daftar dan mengonversi ke string. Berorientasi pada hasil.str
daripada menerapkannya pada setiap jenis iterable.Jawaban:
Itu karena setiap iterable dapat bergabung (misalnya, daftar, tuple, dict, set), tetapi hasil dan "joiner" harus berupa string.
Sebagai contoh:
Menggunakan sesuatu selain string akan memunculkan kesalahan berikut:
sumber
list.join(string)
muncul lebih pendekatan berorientasi objek sedangkanstring.join(list)
terdengar jauh lebih prosedural bagi saya.print(str.join('-', my_list))
dan berfungsi, terasa lebih baik.__iter__
metode. Membutuhkan semua iterables untuk diimplementasikan jugajoin
akan mempersulit antarmuka umum (yang juga mencakup iterables atas non-string) untuk kasus penggunaan yang sangat khusus. Menentukanjoin
pada strins langkah-langkah masalah ini dengan mengorbankan pesanan "tidak intuitif". Pilihan yang lebih baik mungkin tetap berfungsi dengan argumen pertama menjadi iterable dan yang kedua (opsional) menjadi string joiner - tetapi kapal telah berlayar.Ini dibahas dalam metode String ... akhirnya utas dengan Python-Dev, dan diterima oleh Guido. Utas ini dimulai pada Juni 1999, dan
str.join
termasuk dalam Python 1.6 yang dirilis pada Sep 2000 (dan mendukung Unicode). Python 2.0 (str
termasuk metode yang didukungjoin
) dirilis pada Oktober 2000.str.join(seq)
seq.join(str)
seq.reduce(str)
join
sebagai fungsi bawaanlist
s,tuple
s, tetapi semua urutan / iterables.seq.reduce(str)
sulit bagi pendatang baru.seq.join(str)
memperkenalkan ketergantungan yang tak terduga dari urutan ke str / unicode.join()
sebagai fungsi bawaan hanya akan mendukung tipe data tertentu. Jadi menggunakan namespace bawaan tidak baik. Jikajoin()
mendukung banyak tipe data, membuat implementasi yang dioptimalkan akan sulit, jika diimplementasikan menggunakan__add__
metode maka O (n²).sep
) tidak boleh dihilangkan. Eksplisit lebih baik daripada implisit.Tidak ada alasan lain yang ditawarkan di utas ini.
Berikut adalah beberapa pemikiran tambahan (milik saya, dan teman saya):
Keputusan Guido dicatat dalam surat historis , memutuskan
str.join(seq)
:sumber
Karena
join()
metode ini di kelas string, bukan kelas daftar?Saya setuju itu terlihat lucu.
Lihat http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
sumber
string
Pustaka Python 3 telah menghapus semuastr
metode yang berlebihan , sehingga Anda tidak bisa lagi menggunakanstring.join()
. Secara pribadi, saya tidak pernah berpikir itu 'lucu', itu masuk akal, karena Anda dapat bergabung lebih dari sekadar daftar, tetapi joiner selalu menjadi string!Saya setuju bahwa itu berlawanan dengan intuisi pada awalnya, tetapi ada alasan bagus. Bergabung tidak dapat menjadi metode daftar karena:
Sebenarnya ada dua metode bergabung (Python 3.0):
Jika bergabung adalah metode daftar, maka ia harus memeriksa argumennya untuk memutuskan yang mana dari mereka yang akan dihubungi. Dan Anda tidak dapat bergabung dengan byte dan str bersama-sama, jadi cara mereka sekarang masuk akal.
sumber
Ini karena
join
metode "string"! Ini menciptakan string dari setiap iterable. Jika kita terjebak metode pada daftar, bagaimana ketika kita memiliki iterables yang bukan daftar?Bagaimana jika Anda memiliki tuple string? Jika ini adalah
list
metode, Anda harus melemparkan setiap iterator string sepertilist
sebelum Anda dapat bergabung dengan elemen menjadi satu string! Sebagai contoh:Mari kita roll metode daftar bergabung kita sendiri:
Dan untuk menggunakannya, perhatikan bahwa kita harus terlebih dahulu membuat daftar dari setiap iterable untuk bergabung dengan string di iterable, membuang-buang memori dan kekuatan pemrosesan:
Jadi kami melihat kami harus menambahkan langkah ekstra untuk menggunakan metode daftar kami, daripada hanya menggunakan metode string bawaan:
Peringatan Kinerja untuk Generator
Algoritma yang digunakan Python untuk membuat string terakhir dengan
str.join
benar - benar harus melewati iterable dua kali, jadi jika Anda memberikannya ekspresi generator, itu harus terwujud menjadi daftar terlebih dahulu sebelum dapat membuat string terakhir.Dengan demikian, sementara membagikan generator biasanya lebih baik daripada daftar pemahaman,
str.join
adalah pengecualian:Namun demikian,
str.join
operasi ini masih semantik operasi "string", sehingga masih masuk akal untuk memilikinya padastr
objek daripada pada iterables lain-lain.sumber
Anggap saja sebagai operasi ortogonal alami untuk membelah.
Saya mengerti mengapa itu berlaku untuk apa pun yang dapat diubah sehingga tidak dapat dengan mudah diimplementasikan hanya pada daftar.
Untuk keterbacaan, saya ingin melihatnya dalam bahasa tetapi saya tidak berpikir itu benar-benar layak - jika iterability adalah sebuah antarmuka maka itu dapat ditambahkan ke antarmuka tetapi itu hanya sebuah konvensi dan jadi tidak ada cara sentral untuk tambahkan ke set hal-hal yang dapat diubah.
sumber
Terutama karena hasil dari a
someString.join()
adalah string.Urutan (daftar atau tupel atau apa pun) tidak muncul dalam hasil, hanya string. Karena hasilnya adalah string, masuk akal sebagai metode string.
sumber
-
di "-". join (my_list) menyatakan bahwa Anda mengonversi string dari bergabung dengan elemen daftar. Berorientasi pada hasil (hanya untuk memori dan pemahaman yang mudah)Saya membuat cheatsheet yang lengkap tentang methods_of_string untuk referensi Anda.
sumber
Keduanya tidak baik.
string.join (xs, delimit) berarti bahwa modul string menyadari keberadaan daftar, yang tidak diketahui oleh bisnis, karena modul string hanya bekerja dengan string.
list.join (delimit) sedikit lebih bagus karena kita sudah terbiasa menggunakan string sebagai tipe fundamental (dan secara bahasa, mereka). Namun ini berarti bahwa join harus dikirim secara dinamis karena dalam konteks arbitrer
a.split("\n")
kompiler python mungkin tidak tahu apa itu, dan akan perlu mencarinya (analog dengan vtable lookup), yang mahal jika Anda melakukannya banyak waktu.jika kompiler runtime python tahu bahwa daftar adalah modul bawaan, ia dapat melewatkan pencarian dinamis dan menyandikan maksud ke dalam bytecode secara langsung, sedangkan sebaliknya ia perlu secara dinamis menyelesaikan "join" dari "a", yang mungkin terdiri atas beberapa lapisan dari inheritence per panggilan (karena di antara panggilan, arti bergabung mungkin telah berubah, karena python adalah bahasa yang dinamis).
Sayangnya, ini adalah kelemahan utama dari abstraksi; tidak peduli apa pun abstraksi yang Anda pilih, abstraksi Anda hanya akan masuk akal dalam konteks masalah yang Anda coba selesaikan, dan dengan demikian Anda tidak akan pernah bisa memiliki abstraksi yang konsisten yang tidak menjadi tidak konsisten dengan ideologi yang mendasari ketika Anda mulai menempelkannya bersama-sama tanpa membungkusnya dalam pandangan yang konsisten dengan ideologi Anda. Mengetahui hal ini, pendekatan python lebih fleksibel karena lebih murah, terserah Anda untuk membayar lebih banyak agar terlihat "lebih bagus", baik dengan membuat bungkus sendiri, atau preprosesor Anda sendiri.
sumber
Variabel
my_list
dan"-"
keduanya objek. Secara khusus, mereka adalah contoh dari kelaslist
danstr
, masing-masing. Thejoin
Fungsi milik kelasstr
. Oleh karena itu, sintaks"-".join(my_list)
digunakan karena objek"-"
mengambilmy_list
sebagai input.sumber