Mengapa string.join(daftar) dan bukan dari daftar.bergabung(string)?

Ini selalu membuatku bingung. Sepertinya ini akan menjadi 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 tertentu hal ini seperti ini?

Mengomentari pertanyaan (4)
Larutan

It's karena setiap iterable dapat bergabung, bukan hanya daftar, tapi hasil dan "joiner" selalu string.

Misalnya:

import urllib2
print('\n############\n'.join(
    urllib2.urlopen('http://data.stackexchange.com/users/7095')))
Komentar (11)

Hal ini telah dibahas dalam String metode... akhirnya thread di Python-Dev mencapai, dan diterima oleh Guido. Thread ini dimulai pada Juni 1999, dan str.bergabung termasuk dalam Python 1.6 yang dirilis pada September 2000 (dan didukung Unicode). Python 2.0 (didukung str metode bergabung) dirilis pada bulan Oktober 2000.

  • Ada empat opsi yang diajukan di thread ini:
  • str.bergabung(seq)
  • seq.bergabung(str)
  • seq.mengurangi(str)
  • bergabung sebagai fungsi built-in
  • Guido ingin mendukung tidak hanya daftar ini,tupel ini, tapi semua urutan/iterables.
  • seq.mengurangi(str) adalah sulit bagi pendatang baru.
  • seq.bergabung(str) memperkenalkan terduga ketergantungan dari urutan ke str/unicode.
  • join() sebagai fungsi built-in yang akan mendukung hanya data spesifik jenis. Jadi menggunakan dibangun di namespace adalah tidak baik. Jika join() mendukung banyak tipe data, membuat dioptimalkan pelaksanaannya akan sulit, jika diimplementasikan dengan menggunakan __add__ metode maka's O(n²).
  • Pemisah string (sep) tidak boleh dihilangkan. Eksplisit lebih baik dari yang implisit.

Tidak ada alasan lain yang ditawarkan di thread ini.

Berikut ini adalah beberapa tambahan pikiran (saya sendiri, dan teman saya's):

  • Dukungan Unicode datang, tapi itu belum final. Pada waktu itu UTF-8 adalah yang paling mungkin untuk menggantikan UCS2/4. Untuk menghitung total panjang penyangga dari string UTF-8 yang dibutuhkan untuk mengetahui karakter coding aturan.
  • Pada waktu itu, Python sudah memutuskan pada urutan umum antarmuka aturan di mana pengguna dapat membuat urutan-suka (iterable) kelas. Tapi Python didn't memperluas dukungan built-in jenis sampai 2.2. Pada waktu itu sulit untuk memberikan dasar iterable kelas (yang disebutkan dalam komentar yang lain).

Guido's keputusan yang tercatat dalam sejarah mail, memutuskan str.bergabung(seq):

Lucu, tapi itu tampaknya benar! Barry, pergi untuk itu... --Guido van Rossum

Komentar (0)

Karena join() metode dalam class string, bukan daftar kelas?

Saya setuju itu terlihat lucu.

Lihat http://www.faqs.org/docs/diveintopython/odbchelper_join.html:

catatan Sejarah. Ketika saya pertama kali belajar Python, saya diharapkan untuk bergabung menjadi metode dari daftar, yang akan mengambil pembatas sebagai argumen. Banyak orang-orang yang merasakan hal yang sama, dan ada cerita di balik metode join. Sebelum untuk Python 1.6, string tidak memiliki semua ini metode yang berguna. Ada memisahkan string modul yang terkandung semua fungsi string; masing-masing fungsi mengambil string sebagai yang pertama argumen. Fungsi dianggap cukup penting untuk dimasukkan ke string diri mereka sendiri, yang membuat rasa untuk fungsi-fungsi seperti lower, upper, dan split. Tapi banyak hard-core Python programmer keberatan untuk yang baru bergabung metode, dengan alasan bahwa hal itu harus menjadi metode daftar sebaliknya, atau bahwa itu tidak bergerak sama sekali, tetapi hanya tinggal bagian dari string tua modul (yang masih memiliki banyak hal-hal yang berguna di dalamnya). saya gunakan baru bergabung dengan metode eksklusif, tetapi anda akan melihat kode yang ditulis dengan baik cara, dan jika itu benar-benar mengganggu anda, anda dapat menggunakan string tua.bergabung fungsi sebagai gantinya.

--- Tanda Haji, Dive into Python

Komentar (1)

Saya setuju bahwa itu's berlawanan dengan intuisi, tapi ada's sebuah alasan yang baik. Bergabung bisa't menjadi metode dari daftar karena:

  • ia harus bekerja untuk berbagai iterables juga (tupel, generator, dll.)
  • itu harus memiliki perilaku yang berbeda antara jenis yang berbeda dari string.

Sebenarnya ada dua bergabung metode (Python 3.0):

>>> b"".join

>>> "".join

Jika bergabung adalah metode daftar, maka akan memiliki untuk memeriksa argumen untuk memutuskan mana salah satu dari mereka untuk menelepon. Dan anda dapat't bergabung byte dan str bersama-sama, sehingga mereka itu sekarang masuk akal.

Komentar (0)

Mengapa string.join(daftar) bukan daftar.bergabung(string)?

Hal ini karena bergabung adalah "string" metode! Ini menciptakan sebuah string dari setiap iterable. Jika kita terjebak pada metode daftar, bagaimana ketika kita memiliki iterables yang tidak't daftar?

Bagaimana jika anda memiliki sebuah tuple dari string? Jika ini adalah sebuah daftar metode, anda akan memiliki untuk melemparkan setiap iterasi dari string sebagai daftar sebelum anda dapat bergabung dengan unsur-unsur dalam sebuah string tunggal! Misalnya:

some_strings = ('foo', 'bar', 'baz')

Let's roll kami daftar sendiri bergabung dengan metode:

class OurList(list): 
    def join(self, s):
        return s.join(self)

Dan untuk menggunakannya, perhatikan bahwa kita harus terlebih dahulu membuat daftar dari masing-masing iterable untuk bergabung dengan string yang iterable, membuang-buang memori dan daya proses:

>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'

Jadi kita lihat kita harus menambahkan langkah tambahan untuk menggunakan metode daftar, bukan hanya menggunakan builtin string metode:

>>> ' | '.join(some_strings) # a single step!
'foo | bar | baz'

Kinerja Peringatan untuk Generator

Algoritma ini menggunakan Python untuk membuat final string dengan str.bergabung benar-benar telah melewati iterable dua kali, jadi jika anda memberikan sebuah generator ekspresi, itu telah terwujud menjadi daftar pertama sebelum dapat membuat akhir string.

Dengan demikian, saat melintas di sekitar generator biasanya lebih baik dari daftar pemahaman, str.bergabung adalah pengecualian:

>>> import timeit
>>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
3.839168446022086
>>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
3.339879313018173

Namun demikian, str.bergabung dengan operasi masih semantik "string" operasi, jadi masih masuk akal untuk memiliki itu pada str objek dari pada lain-lain iterables.

Komentar (0)

Berpikir itu sebagai alam orthogonal operasi untuk membagi.

Saya memahami mengapa hal ini berlaku untuk apa pun iterable dan agar bisa't mudah dilaksanakan hanya pada daftar.

Untuk dibaca, saya'd ingin melihat itu dalam bahasa tapi aku don't pikir itu benar-benar layak - jika iterability adalah sebuah antarmuka maka bisa ditambahkan ke antarmuka tapi itu hanya sebuah convention dan jadi ada's tidak ada cara untuk menambahkan ini ke set dari hal-hal yang iterable.

Komentar (0)

Terutama karena hasil dari someString.join() adalah string.

Urutan (daftar atau tupel atau apapun) doesn't muncul di hasil, hanya string. Karena hasilnya adalah string, itu masuk akal sebagai metode string.

Komentar (0)

- di "-".bergabung(my_list) menyatakan bahwa anda konversi ke string dari bergabung dengan unsur-unsur daftar.It's berorientasi hasil.(hanya untuk memudahkan ingatan dan pemahaman)

Saya membuat lengkap cheatsheet dari methods_of_string untuk referensi anda.

string_methonds_44 = {
    'convert': ['join','split', 'rsplit','splitlines', 'partition', 'rpartition'],
    'edit': ['replace', 'lstrip', 'rstrip', 'strip'],
    'search': ['endswith', 'startswith', 'count', 'index', 'find','rindex', 'rfind',],
    'condition': ['isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isnumeric','isidentifier',
                  'islower','istitle', 'isupper','isprintable', 'isspace', ],
    'text': ['lower', 'upper', 'capitalize', 'title', 'swapcase',
             'center', 'ljust', 'rjust', 'zfill', 'expandtabs','casefold'],
    'encode': ['translate', 'maketrans', 'encode'],
    'format': ['format', 'format_map']}
Komentar (0)

Keduanya tidak bagus.

string.bergabung(xs, membatasi) berarti bahwa string modul menyadari keberadaan dari sebuah daftar, yang tidak memiliki bisnis yang mengetahui tentang, sejak string modul ini hanya akan bekerja dengan string.

daftar.bergabung(membatasi) adalah sedikit lebih bagus karena kita're sehingga digunakan untuk string yang mendasar jenis(dan lingual berbicara, mereka). Namun ini berarti bahwa bergabung kebutuhan akan dikirim secara dinamis karena dalam sewenang-wenang konteks a.split("\n") compiler python mungkin tidak tahu apa yang lebih, dan akan perlu untuk melihat itu(analog untuk vtable lookup), yang lebih mahal jika anda melakukannya banyak kali.

jika python runtime compiler tahu bahwa daftar yang dibangun di modul, maka dapat melewatkan dinamis lookup dan encode maksud ke dalam bytecode langsung, sedangkan jika tidak maka kebutuhan untuk secara dinamis mengatasi "bergabung" "", yang mungkin sampai beberapa lapisan inheritence per panggilan(karena antara panggilan, makna bergabung dapat berubah, karena python merupakan bahasa dinamis).

sayangnya, ini adalah yang paling cacat abstraksi; tidak peduli apa abstraksi yang anda pilih, anda abstraksi hanya akan masuk akal dalam konteks masalah anda're mencoba untuk memecahkan, dan seperti anda tidak pernah memiliki konsisten abstraksi yang doesn't menjadi tidak konsisten dengan ideologi yang mendasari seperti yang anda mulai menempelkan mereka bersama-sama tanpa membungkus mereka dalam tampilan yang konsisten dengan ideologi anda. Mengetahui hal ini, python's pendekatan ini lebih fleksibel karena itu's lebih murah, it's terserah anda untuk membayar lebih untuk membuatnya terlihat "bagus", baik dengan membuat anda sendiri wrapper, atau anda sendiri preprocessor.

Komentar (0)

Variabel my_list dan "-" apakah kedua benda. Secara khusus, mereka're contoh kelas daftar dan str, masing-masing. Join fungsi termasuk kelas str. Oleh karena itu, sintaks "-".bergabung(my_list) digunakan karena objek "-" mengambil my_list sebagai input.

Komentar (0)