Antipattern yang umum dalam Python adalah menggabungkan urutan string menggunakan +
dalam satu lingkaran. Ini buruk karena penerjemah Python harus membuat objek string baru untuk setiap iterasi, dan akhirnya memakan waktu kuadrat. (Versi terbaru CPython tampaknya dapat mengoptimalkan ini dalam beberapa kasus, tetapi implementasi lain tidak dapat melakukannya, sehingga pemrogram tidak disarankan untuk mengandalkan ini.) ''.join
Adalah cara yang tepat untuk melakukan ini.
Namun, saya pernah mendengarnya mengatakan ( termasuk di sini di Stack Overflow ) bahwa Anda tidak boleh pernah menggunakan +
untuk penggabungan string, tetapi selalu menggunakan ''.join
atau format string. Saya tidak mengerti mengapa ini terjadi jika Anda hanya menggabungkan dua string. Jika pemahaman saya benar, tidak perlu waktu kuadrat, dan menurut saya a + b
lebih bersih dan mudah dibaca daripada ''.join((a, b))
atau '%s%s' % (a, b)
.
Apakah praktik yang baik menggunakan +
menggabungkan dua string? Atau apakah ada masalah yang tidak saya sadari?
+
lebih cepat atau lebih lambat? Dan mengapa?In [2]: %timeit "a"*80 + "b"*80
1000000 loops, best of 3: 356 ns per loop
In [3]: %timeit "%s%s" % ("a"*80, "b"*80)
1000000 loops, best of 3: 907 ns per loop
In [3]: %timeit "%s%s" % (a, b) 1000000 loops, best of 3: 590 ns per loop
In [4]: %timeit a + b 10000000 loops, best of 3: 147 ns per loop
__str__
. Lihat jawaban saya untuk contoh.Jawaban:
Tidak ada salahnya menggabungkan dua string dengan
+
. Memang lebih mudah dibaca daripada''.join([a, b])
.Anda benar meskipun menggabungkan lebih dari 2 string dengan
+
adalah operasi O (n ^ 2) (dibandingkan dengan O (n) untukjoin
) dan dengan demikian menjadi tidak efisien. Namun ini tidak ada hubungannya dengan menggunakan loop. Evena + b + c + ...
adalah O (n ^ 2), alasannya adalah bahwa setiap rangkaian menghasilkan string baru.CPython2.4 dan yang lebih baru mencoba menguranginya, tetapi tetap disarankan untuk digunakan
join
saat menggabungkan lebih dari 2 string.sumber
.join
mengambil iterable, sehingga kedua.join([a,b])
dan.join((a,b))
berlaku.+
atau+=
dalam jawaban yang diterima (dari 2013) di stackoverflow.com/a/12171382/378826 (dari Lennart Regebro) bahkan untuk CPython 2.3+ dan untuk hanya memilih pola "tambahkan / gabung" jika penjelas ini mengekspos ide untuk solusi masalah yang ada.Operator Plus adalah solusi yang sangat baik untuk menggabungkan dua string Python. Tetapi jika Anda terus menambahkan lebih dari dua string (n> 25), Anda mungkin ingin memikirkan hal lain.
''.join([a, b, c])
trik adalah pengoptimalan kinerja.sumber
append()
memasukkan string ke daftar.n > 25
. Manusia membutuhkan titik referensi untuk memulai suatu tempat.Asumsi bahwa seseorang seharusnya tidak pernah menggunakan + untuk penggabungan string, tetapi selalu menggunakan ".join mungkin hanya mitos. Memang benar bahwa menggunakan
+
membuat salinan sementara yang tidak perlu dari objek string yang tidak dapat diubah, tetapi fakta lain yang tidak sering dikutip adalah bahwa pemanggilanjoin
dalam satu loop umumnya akan menambah overheadfunction call
. Mari kita ambil contoh Anda.Buat dua daftar, satu dari pertanyaan SO yang ditautkan dan yang lainnya dibuat lebih besar
Mari kita buat dua fungsi,
UseJoin
danUsePlus
untuk menggunakan masing-masingjoin
dan+
fungsionalitas.Mari kita jalankan timeit dengan daftar pertama
Mereka memiliki runtime yang hampir sama.
Mari kita gunakan cProfile
Dan tampaknya menggunakan Gabung, menghasilkan pemanggilan fungsi yang tidak perlu yang dapat menambah overhead.
Sekarang kembali ke pertanyaan. Haruskah seseorang mencegah penggunaan
+
overjoin
dalam semua kasus?Saya percaya tidak, hal-hal harus dipertimbangkan
Dan di luar jalur dalam pengembangan, pengoptimalan pra-matang adalah jahat.
sumber
join
di dalam loop itu sendiri - melainkan loop akan menghasilkan urutan yang akan diteruskan untuk bergabung.Saat bekerja dengan banyak orang, terkadang sulit untuk mengetahui dengan tepat apa yang terjadi. Menggunakan format string alih-alih penggabungan dapat menghindari satu gangguan tertentu yang terjadi berkali-kali kepada kami:
Katakanlah, sebuah fungsi membutuhkan argumen, dan Anda menulisnya dengan harapan mendapatkan string:
Jadi, fungsi ini mungkin cukup sering digunakan di seluruh kode. Rekan kerja Anda mungkin tahu persis apa fungsinya, tetapi belum tentu sepenuhnya mengetahui kecepatan internal, dan mungkin tidak tahu bahwa fungsi tersebut mengharapkan string. Dan mereka mungkin akan berakhir dengan ini:
Tidak akan ada masalah jika Anda hanya menggunakan string format:
Hal yang sama juga berlaku untuk semua jenis objek
__str__
yang ditentukan, yang mungkin diteruskan juga:Jadi ya: Jika Anda dapat menggunakan string format, lakukan dan manfaatkan apa yang ditawarkan Python.
sumber
+
.zeta = u"a\xac\u1234\u20ac\U00008000"
- jadi Anda harus menggunakanprint 'bar: ' + unicode(zeta)
untuk memastikan itu tidak error.%s
melakukannya dengan benar tanpa harus memikirkannya, dan jauh lebih pendek"bar: %s"
mungkin diterjemahkan ke"zrb: %s br"
dalam beberapa bahasa lain. The%s
versi akan hanya bekerja, tapi versi string concat akan menjadi berantakan untuk menangani semua kasus dan penerjemah Anda sekarang akan memiliki dua terjemahan yang terpisah untuk menanganidef
.Saya telah melakukan tes cepat:
dan waktunya:
Tampaknya ada optimasi untuk
a = a + b
kasus tersebut. Ini tidak menunjukkan waktu O (n ^ 2) seperti yang diduga.Jadi setidaknya dalam hal kinerja, penggunaan
+
itu baik-baik saja.sumber
Menurut dokumen Python, menggunakan str.join () akan memberi Anda konsistensi kinerja di berbagai implementasi Python. Meskipun CPython mengoptimalkan perilaku kuadrat s = s + t, implementasi Python lainnya mungkin tidak.
Jenis Urutan dalam dokumen Python (lihat catatan kaki [6])
sumber
Saya menggunakan yang berikut ini dengan python 3.8
sumber
'' .join ([a, b]) adalah solusi yang lebih baik daripada + .
Karena Kode harus ditulis dengan cara yang tidak merugikan implementasi Python lainnya (PyPy, Jython, IronPython, Cython, Psyco, dan semacamnya)
bentuk a + = b atau a = a + b rapuh bahkan di CPython dan tidak ada sama sekali dalam implementasi yang tidak menggunakan penghitungan ulang (penghitungan referensi adalah teknik untuk menyimpan jumlah referensi, pointer, atau pegangan ke sumber daya seperti objek, blok memori, ruang disk, atau sumber daya lainnya )
https://www.python.org/dev/peps/pep-0008/#programming-recommendations
sumber
a += b
bekerja di semua implementasi Python, hanya saja pada beberapa di antaranya dibutuhkan waktu kuadrat ketika dilakukan di dalam loop ; pertanyaannya adalah tentang penggabungan string luar loop.