Kelas string Python seperti StringBuilder di C #?

121

Apakah ada beberapa kelas string dalam Python seperti StringBuilderdi C #?

icn
sumber
6
Ini adalah duplikat Python yang setara dengan Java StringBuffer . PERHATIAN: Jawaban di sini sangat kuno dan, pada kenyataannya, menyesatkan. Lihat pertanyaan lain untuk jawaban yang lebih relevan dengan versi Python modern (tentu saja 2.7 ke atas).
Jean-François Corbett

Jawaban:

102

Tidak ada korelasi satu-ke-satu. Untuk artikel yang sangat bagus, silakan lihat Penggabungan String yang Efisien dengan Python :

Membangun string panjang dalam bahasa pemrograman Python terkadang dapat menghasilkan kode yang berjalan sangat lambat. Pada artikel ini saya menyelidiki kinerja komputasi berbagai metode penggabungan string.

Andrew Hare
sumber
27
Perhatikan bahwa artikel ini ditulis berdasarkan Python 2.2. Tes kemungkinan akan keluar agak berbeda dalam versi modern Python (CPython biasanya berhasil mengoptimalkan penggabungan, tetapi Anda tidak ingin bergantung pada ini dalam kode penting) dan ekspresi generator di mana dia menggunakan pemahaman daftar akan layak dipertimbangkan .
Mike Graham
4
Akan lebih baik untuk menarik beberapa sorotan dalam artikel itu, setidaknya beberapa implementasi (untuk menghindari masalah pembusukan tautan).
jpmc26
3
Metode 1: resultString + = appendString adalah yang tercepat menurut tes oleh @ Antoine-tran di bawah ini
Justas
5
Kutipan Anda sama sekali tidak menjawab pertanyaan itu. Harap sertakan bagian yang relevan dalam jawaban Anda sendiri, untuk mematuhi pedoman baru.
Gugatan Dana Monica
27

Saya telah menggunakan kode Oliver Crow (tautan yang diberikan oleh Andrew Hare) dan sedikit mengadaptasinya untuk menyesuaikan Python 2.7.3. (dengan menggunakan paket timeit). Saya menjalankan komputer pribadi saya, Lenovo T61, RAM 6GB, Debian GNU / Linux 6.0.6 (pemerasan).

Berikut hasil untuk 10.000 iterasi:

metode1: 0,0538418292999 dtk
ukuran proses 4800 kb
metode2: 0,22602891922 dtk
ukuran proses 4960 kb
method3: 0,0605459213257 detik
ukuran proses 4980 kb
method4: 0,0544030666351 detik
ukuran proses 5536 kb
metode5: 0,0551080703735 detik
ukuran proses 5272 kb
method6: 0,0542731285095 detik
ukuran proses 5512 kb

dan untuk 5.000.000 iterasi (metode 2 diabaikan karena berjalan terlalu lambat, seperti selamanya):

method1: 5.88603997231 detik
ukuran proses 37976 kb
method3: 8.40748500824 detik
ukuran proses 38024 kb
method4: 7.96380496025 detik
ukuran proses 321968 kb
method5: 8.03666186333 detik
ukuran proses 71720 kb
method6: 6.68192911148 detik
ukuran proses 38240 kb

Sangat jelas bahwa orang-orang Python telah melakukan pekerjaan yang cukup bagus untuk mengoptimalkan penggabungan string, dan seperti yang dikatakan Hoare: "pengoptimalan prematur adalah akar dari semua kejahatan" :-)

Antoine-tran
sumber
2
Rupanya Hoare tidak menerima itu: hans.gerwitz.com/2004/08/12/…
Pimin Konstantin Kefaloukos
5
Ini bukanlah pengoptimalan yang prematur untuk menghindari pengoptimalan yang rapuh dan bergantung pada interpreter. Jika Anda ingin melakukan porting ke PyPy atau berisiko terkena salah satu dari banyak kasus kegagalan halus untuk pengoptimalan, lakukan hal-hal dengan cara yang benar.
Veedrac
1
Sepertinya Metode 1 lebih mudah untuk dioptimalkan oleh kompilator.
mbomb007
25

Mengandalkan pengoptimalan kompiler itu rapuh. Tolok ukur yang ditautkan dalam jawaban yang diterima dan angka yang diberikan oleh Antoine-tran tidak bisa dipercaya. Andrew Hare membuat kesalahan dengan memasukkan panggilan ke reprdalam metodenya. Itu memperlambat semua metode secara sama tetapi mengaburkan penalti sebenarnya dalam membangun string.

Gunakan join. Ini sangat cepat dan lebih kuat.

$ ipython3
Python 3.5.1 (default, Mar  2 2016, 03:38:02) 
IPython 4.1.2 -- An enhanced Interactive Python.

In [1]: values = [str(num) for num in range(int(1e3))]

In [2]: %%timeit
   ...: ''.join(values)
   ...: 
100000 loops, best of 3: 7.37 µs per loop

In [3]: %%timeit
   ...: result = ''
   ...: for value in values:
   ...:     result += value
   ...: 
10000 loops, best of 3: 82.8 µs per loop

In [4]: import io

In [5]: %%timeit
   ...: writer = io.StringIO()
   ...: for value in values:
   ...:     writer.write(value)
   ...: writer.getvalue()
   ...: 
10000 loops, best of 3: 81.8 µs per loop
GrantJ
sumber
Ya, reprpanggilan mendominasi waktu proses, tetapi Anda tidak perlu membuat kesalahan menjadi pribadi.
Alex Reinking
3
@AlexReinking maaf, tidak ada maksud pribadi. Saya tidak yakin apa yang membuat Anda berpikir itu bersifat pribadi. Tetapi jika itu adalah penggunaan nama mereka, saya menggunakan itu hanya untuk merujuk pada jawaban pengguna (cocok dengan nama pengguna, tidak yakin apakah ada cara yang lebih baik).
GrantJ
1
contoh waktu yang baik yang memisahkan inisialisasi data dan operasi penggabungan
aiodintsov
19

Python memiliki beberapa hal yang memenuhi tujuan serupa:

  • Salah satu cara umum untuk membuat string besar dari potongan-potongan adalah dengan mengembangkan daftar string dan menggabungkannya setelah Anda selesai. Ini adalah idiom Python yang sering digunakan.
    • Untuk membangun string yang menggabungkan data dengan pemformatan, Anda akan melakukan pemformatan secara terpisah.
  • Untuk penyisipan dan penghapusan pada tingkat karakter, Anda akan menyimpan daftar string panjang satu. (Untuk membuat ini dari string, Anda akan memanggil list(your_string). Anda juga bisa menggunakan a UserString.MutableStringuntuk ini.
  • (c)StringIO.StringIO berguna untuk hal-hal yang seharusnya mengambil file, tetapi kurang berguna untuk pembuatan string umum.
Mike Graham
sumber
10

Dengan menggunakan metode 5 dari atas (The Pseudo File) kita bisa mendapatkan kinerja dan fleksibilitas yang sangat baik

from cStringIO import StringIO

class StringBuilder:
     _file_str = None

     def __init__(self):
         self._file_str = StringIO()

     def Append(self, str):
         self._file_str.write(str)

     def __str__(self):
         return self._file_str.getvalue()

sekarang menggunakannya

sb = StringBuilder()

sb.Append("Hello\n")
sb.Append("World")

print sb
Thomas Watson
sumber
4

Anda dapat mencoba StringIO atau cStringIO

anjing hantu74
sumber
-1

Tidak ada analog eksplisit - saya pikir Anda diharapkan menggunakan rangkaian string (kemungkinan dioptimalkan seperti yang dikatakan sebelumnya) atau kelas pihak ketiga (saya ragu mereka jauh lebih efisien - daftar di python diketik dinamis jadi tidak bekerja cepat char [] untuk buffer seperti yang saya asumsikan). Kelas seperti pembuat string bukanlah pengoptimalan prematur karena fitur bawaan string dalam banyak bahasa (kekekalan) - yang memungkinkan banyak pengoptimalan (misalnya, merujuk buffer yang sama untuk irisan / substring). Kelas Stringbuilder / stringbuffer / seperti stringstream bekerja jauh lebih cepat daripada string gabungan (menghasilkan banyak objek sementara kecil yang masih membutuhkan alokasi dan pengumpulan sampah) dan bahkan alat pemformatan string seperti printf, tidak perlu menafsirkan overhead pola pemformatan yang cukup memakan waktu banyak panggilan format.

Dalang
sumber
-4

Jika Anda di sini mencari metode penggabungan string cepat dengan Python, maka Anda tidak memerlukan kelas StringBuilder khusus. Rangkaian sederhana bekerja dengan baik tanpa penalti kinerja yang terlihat di C #.

resultString = ""

resultString += "Append 1"
resultString += "Append 2"

Lihat jawaban Antoine-tran untuk hasil kinerja

Justas
sumber