Banyak cara pemformatan string Python - apakah yang lebih lama (akan) tidak digunakan lagi?

106

Python memiliki setidaknya enam cara memformat string:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

Sejarah singkat dari berbagai metode:

  • printfpemformatan gaya telah ada sejak Pythons masih bayi
  • The Templatekelas diperkenalkan dengan Python 2.4
  • The formatMetode diperkenalkan dengan Python 2.6
  • f-string diperkenalkan dengan Python 3.6

Pertanyaan saya adalah:

  • Apakah printfpemformatan gaya tidak berlaku lagi atau akan dihentikan?
  • Di Template class, apakah substitutemetode ini tidak digunakan lagi atau akan dihentikan? (Saya tidak berbicara tentang safe_substitute, yang menurut saya menawarkan kemampuan unik)

Pertanyaan serupa dan mengapa menurut saya itu bukan duplikat:

  • Pemformatan string Python:% vs. .format - hanya memperlakukan metode 1 dan 2, dan menanyakan mana yang lebih baik; pertanyaan saya secara eksplisit tentang deprecation in the Zen of Python

  • Opsi pemformatan string: pro dan kontra - hanya memperlakukan metode 1a dan 1b dalam pertanyaan, 1 dan 2 dalam jawaban, dan juga tidak ada tentang penghentian

  • pemformatan string lanjutan vs string template - sebagian besar tentang metode 1 dan 3, dan tidak membahas penghentian

  • Ekspresi pemformatan string (Python) - jawaban menyebutkan bahwa pendekatan '%' asli direncanakan untuk dihentikan . Tapi apa perbedaan antara direncanakan untuk dihentikan , menunggu penolakan, dan penghentian yang sebenarnya ? Dan printfmetode -style tidak menghasilkan a PendingDeprecationWarning, jadi apakah ini benar-benar akan ditinggalkan? Posting ini juga cukup lama, jadi informasinya mungkin sudah ketinggalan zaman.

Lihat juga

gerrit
sumber
1
Apakah saya perlu menunjukkan bahwa Anda lupa Formatterkelasnya?
Martijn Pieters

Jawaban:

14

Meskipun ada berbagai indikasi di dokumen bahwa .formatdan f-string lebih unggul dari %string, tidak ada rencana yang bertahan untuk mencabut yang terakhir.

Dalam commit Masalah # 14123: Secara eksplisit menyebutkan bahwa pemformatan% string gaya lama memiliki peringatan tapi tidak akan hilang dalam waktu dekat. , terinspirasi oleh masalah Tunjukkan bahwa saat ini tidak ada rencana untuk menghentikan pemformatan gaya printf , dokumen yang %sedang diformat telah diedit untuk memuat frasa ini:

Karena sintaks pemformatan string baru lebih fleksibel dan menangani tupel dan kamus secara alami, disarankan untuk kode baru. Namun, saat ini tidak ada rencana untuk menghentikan pemformatan gaya printf .

(Penekanan milikku.)

Frasa ini telah dihapus kemudian, di commit Tutup # 4966: ubah urutan dokumen untuk lebih menjelaskan keadaan Python modern . Ini mungkin tampak seperti pertanda bahwa rencana untuk menghentikan %pemformatan telah kembali ke kartu ... tetapi menelusuri pelacak bug mengungkapkan bahwa maksudnya sebaliknya. Di pelacak bug, penulis komit mencirikan perubahan seperti ini :

  • mengubah prosa yang menjelaskan hubungan antara pemformatan gaya printf dan metode str.format (dengan sengaja menghilangkan implikasi bahwa yang pertama adalah bahaya nyata untuk menghilang - tidak praktis bagi kita untuk secara serius mempertimbangkan untuk mematikannya)

Dengan kata lain, kami memiliki dua perubahan berturut-turut pada %dokumen -pemformatan yang dimaksudkan untuk secara eksplisit menekankan bahwa itu tidak akan ditinggalkan, apalagi dihapus. Dokumen tetap berpendapat tentang manfaat relatif dari berbagai jenis pemformatan string, tetapi mereka juga jelas bahwa- %pemformatan tidak akan ditinggalkan atau dihapus.

Terlebih lagi, perubahan terbaru pada paragraf itu , pada Maret 2017, mengubahnya dari ini ...

Operasi pemformatan yang dijelaskan di sini menunjukkan berbagai kebiasaan yang menyebabkan sejumlah kesalahan umum (seperti gagal menampilkan tupel dan kamus dengan benar). Menggunakan literal string berformat yang lebih baru atau str.formatantarmuka membantu menghindari kesalahan ini. Alternatif ini juga memberikan pendekatan yang lebih kuat, fleksibel dan dapat diperluas untuk memformat teks.

... untuk ini:

Operasi pemformatan yang dijelaskan di sini menunjukkan berbagai kebiasaan yang menyebabkan sejumlah kesalahan umum (seperti gagal menampilkan tupel dan kamus dengan benar). Menggunakan literal string berformat yang lebih baru, str.formatantarmuka, atau string template dapat membantu menghindari kesalahan ini. Masing-masing alternatif ini memberikan trade-off dan keuntungannya sendiri berupa kesederhanaan, fleksibilitas, dan / atau ekstensibilitas.

Perhatikan perubahan dari "membantu menghindari" menjadi "dapat membantu menghindari", dan bagaimana rekomendasi yang jelas dari .formatdan f-string telah diganti dengan prosa yang halus dan samar-samar tentang bagaimana setiap gaya "memberikan keuntungan dan keuntungan mereka sendiri" . Artinya, tidak hanya penghentian formal tidak lagi di kartu, tetapi dokumen saat ini secara terbuka mengakui bahwa %pemformatan setidaknya memiliki beberapa "manfaat" dibandingkan pendekatan lainnya.

Saya akan menyimpulkan dari semua ini bahwa gerakan untuk mencela atau menghapus %format tidak hanya tersendat, tetapi juga telah dikalahkan secara menyeluruh dan permanen.

Mark Amery
sumber
2
Perubahan bahasa halus ditambahkan untuk menenangkan pengelola Mercurial (antara lain) yang tidak ingin Mercurial tertinggal dengan basis kode yang terlalu besar untuk diberantas penggunaannya %. Sekarang karena kebijakan 'tidak ada mod kode skala besar' telah dihapus, keberatan mereka juga memudar. Dalam jangka panjang, mempertahankan kedua formulir dengan tidak ada manfaat yang tersisa karena % pada titik tertentu sintaks printf akan tetap dihapus. Kami hanya belum tahu kapan, dan karena itu bahasanya perlu dikurangi.
Martijn Pieters
@ArtijnPenarik. Sepertinya Anda memiliki banyak pengetahuan tentang keputusan yang saya kurang ini. Untuk apa nilainya, saya pikir jawaban yang direferensikan dengan baik dari Anda yang menguraikan poin-poin ini (baik sebagai jawaban baru, atau pengeditan untuk yang sudah ada) akan memiliki nilai.
Mark Amery
58

.format()Metode baru ini dimaksudkan untuk menggantikan %sintaks pemformatan lama . Yang terakhir telah de-menekankan, (tapi tidak secara resmi usang belum ). Dokumentasi metode menyatakan sebanyak:

Metode pemformatan string ini adalah standar baru di Python 3, dan sebaiknya lebih disukai daripada %pemformatan yang dijelaskan dalam Operasi Pemformatan String dalam kode baru.

(Penekanan saya).

Untuk menjaga kompatibilitas mundur dan untuk membuat transisi lebih mudah, format lama telah ditinggalkan untuk saat ini . Dari proposal PEP 3101 asli :

Kompatibilitas Mundur

Kompatibilitas ke belakang dapat dipertahankan dengan membiarkan mekanisme yang ada pada tempatnya. Sistem baru tidak bertabrakan dengan salah satu nama metode dari teknik pemformatan string yang ada, sehingga kedua sistem dapat hidup berdampingan hingga tiba saatnya untuk menghentikan sistem yang lebih lama.

Perhatikan sampai tiba waktunya untuk menghentikan sistem yang lebih lama ; itu belum usang, tetapi sistem baru akan digunakan setiap kali Anda menulis kode baru .

Keunggulan sistem baru ini adalah Anda dapat menggabungkan pendekatan tupel dan kamus dari %pemformat lama :

"{greeting}, {0}".format(world, greeting='Hello')

dan dapat object.__format__()dikembangkan melalui pengait yang digunakan untuk menangani pemformatan nilai individu.

Perhatikan bahwa sistem lama memiliki %dan Templatekelas, di mana yang terakhir memungkinkan Anda untuk membuat subclass yang menambah atau mengubah perilakunya. Sistem gaya baru memiliki Formatterkelas untuk mengisi ceruk yang sama.

Python 3 telah lebih jauh melangkah jauh dari bantahan, bukan memberikan peringatan dalam printfString Formatting -gaya bagian :

Catatan : Operasi pemformatan yang dijelaskan di sini menunjukkan berbagai kebiasaan yang menyebabkan sejumlah kesalahan umum (seperti gagal menampilkan tupel dan kamus dengan benar). Menggunakan literal string berformat yang lebih baru atau str.format()antarmuka membantu menghindari kesalahan ini. Alternatif ini juga memberikan pendekatan yang lebih kuat, fleksibel dan dapat diperluas untuk memformat teks.

Python 3.6 juga menambahkan literal string yang diformat , yang menyejajarkan ekspresi ke dalam format string. Ini adalah metode tercepat untuk membuat string dengan nilai interpolasi, dan harus digunakan di str.format()mana pun Anda dapat menggunakan literal.

Martijn Pieters
sumber
4
Dan dengan FormatterAnda dapat membuat format kustom seperti yang datetimedigunakan objek. Selain itu, karena .formatadalah sebuah fungsi, Anda dapat menggunakannya untuk membuat pemformatan malas yang dapat dipanggil secara lebih langsung: misalnya,fmt = '{} - {}'.format; fmt(a, b)
Jon Clements
Saya tidak melihat bagaimana Templateterkait dengan %atau dengan sistem lama . Secara khusus PEP yang Anda tautkan menyatakan Meskipun ada beberapa tumpang tindih antara proposal ini dan string.Template, dirasakan bahwa masing-masing melayani kebutuhan yang berbeda, dan yang satu tidak meniadakan yang lain. Dalam jawaban Anda, orang mungkin bingung bahwa Templatepemformatan, sebagai bagian dari sistem lama , juga tidak digunakan lagi.
Bakuriu
@ Bakuriu: Benar, saya pikir saya melewatkan bagian itu; tapi menurut saya Formatterkelas bisa memenuhi kebutuhan yang sama seperti string.Template().
Martijn Pieters
1
[...]should be preferred to the % formatting[...]bagian ini telah dihapus dari dokumentasi. docs.python.org/3/library/stdtypes.html#str.format
AXO
Saya pikir jawaban ini sekarang menyesatkan; kutipan pertama telah dihapus dari dokumen Python 3, dan tampaknya cukup jelas bagi saya bahwa tidak ada maksud yang tersisa untuk penghentian terjadi. Jawaban ini masih memiliki nilai historis, tetapi saya cenderung mengubah kata-katanya untuk menghindari saran bahwa penghentian masih ada di kartu, dan mengedit sebagian besar paruh pertama jawaban menjadi dalam bentuk lampau. Saya akan melakukannya sendiri di beberapa titik jika Anda tidak keberatan, tetapi saya pikir saya akan berkomentar terlebih dahulu untuk memberi Anda kesempatan membuat perubahan seperti itu sendiri jika Anda mau.
Mark Amery
45

The %Operator untuk memformat string tidak usang, dan tidak akan dihapus - meskipun jawaban lainnya.
Setiap kali subjek diangkat pada daftar pengembangan Python, ada kontroversi kuat tentang mana yang lebih baik, tetapi tidak ada kontroversi tentang apakah akan menghapus cara klasik - itu akan tetap ada. Meskipun dilambangkan pada PEP 3101, Python 3.1 telah datang dan pergi, dan %pemformatan masih ada.

Pernyataan untuk mempertahankan gaya klasik sudah jelas: sederhana, cepat, cepat dilakukan untuk hal-hal pendek. Menggunakan .formatmetode ini tidak selalu lebih mudah dibaca - dan hampir tidak ada orang - bahkan di antara pengembang inti, dapat menggunakan sintaks lengkap yang disediakan .formattanpa harus melihat referensi Bahkan di tahun 2009, ada pesan seperti ini: http: // mail. python.org/pipermail/python-dev/2009-October/092529.html - subjek hampir tidak muncul di daftar sejak itu.

Pembaruan 2016

Dalam versi pengembangan Python saat ini (yang akan menjadi Python 3.6) ada metode interpolasi string ketiga, dijelaskan pada PEP-0498 . Ini mendefinisikan awalan kutipan baru f""(selain saat ini u"", b""dan r"").

Mengawali string dengan fakan memanggil metode pada objek string saat runtime, yang secara otomatis akan menginterpolasi variabel dari cakupan saat ini ke dalam string:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'
jsbueno
sumber
3
Jauh lebih baik untuk mengizinkan tipe menerapkannya sendiri __format__. Misalnya, format(Decimal('0.1'), '.20f')vs '%.20f' % Decimal('0.1'). Yang terakhir memaksa Desimal menjadi float.
Eryk Sun
2
NB. Saya tidak membantah bahwa gaya lama lebih baik dalam segala hal - hanya saja lebih pendek dan terkadang lebih mudah dibaca (dan terkadang tidak). Tentunya cara baru ini jauh lebih fleksibel.
jsbueno
Apakah ada yang setara dengan fPython 3?
Daniel
The f-stringsseperti yang digunakan di atas adalah fitur baru dalam bahasa sebagai Python 3.6. Itu tidak ada di versi sebelumnya dan akan memunculkan Kesalahan Sintaks pada versi tersebut.
jsbueno
20

Posisi terakhir Guido dalam hal ini tampaknya ditunjukkan di sini:

Apa yang Baru Di Python 3.0

PEP 3101: Pendekatan Baru Untuk Pemformatan String

Sistem baru untuk operasi pemformatan string bawaan menggantikan operator pemformatan% string. (Namun,% operator masih didukung; itu akan ditinggalkan dalam Python 3.1 dan dihapus dari bahasa di lain waktu.) Baca PEP 3101 untuk informasi lengkapnya.

Dan PEP3101 itu sendiri, yang terakhir dimodifikasi sejak (Jum, 30 Sep 2011), jadi tidak ada kemajuan akhir-akhir ini, saya kira.

GSP
sumber
18

Melihat dokumen Python lama dan PEP 3101, terdapat pernyataan bahwa operator% akan ditinggalkan dan dihapus dari bahasa di masa depan. The pernyataan berikut dalam dokumentasi Python untuk Python 3.0, 3.1, dan 3.2:

Karena str.format () cukup baru, banyak kode Python yang masih menggunakan operator%. Namun, karena gaya pemformatan lama ini pada akhirnya akan dihapus dari bahasa, str.format () umumnya harus digunakan.

Jika Anda pergi ke bagian yang sama dalam dokumen Python 3.3 dan 3.4, Anda akan melihat pernyataan itu telah dihapus. Saya juga tidak dapat menemukan pernyataan lain di tempat lain dalam dokumentasi yang menunjukkan bahwa operator tidak akan digunakan lagi atau dihapus dari bahasa tersebut. Penting juga untuk dicatat bahwa PEP3101 belum pernah dimodifikasi selama lebih dari dua setengah tahun (Jum, 30 Sep 2011).

Memperbarui

PEP461 Menambahkan% pemformatan ke byte dan bytearray diterima dan harus menjadi bagian dari Python 3.5 atau 3.6. Ini pertanda lain bahwa operator% masih hidup dan aktif.

Marwan Alsabbagh
sumber