Pertanyaan Pemformatan string Python:% vs.format


Python 2.6 memperkenalkan str.format() metode dengan sintaks yang sedikit berbeda dari yang ada % operator. Mana yang lebih baik dan untuk situasi apa?

  1. Berikut ini menggunakan setiap metode dan memiliki hasil yang sama, jadi apa bedanya?

    #!/usr/bin/python
    sub1 = "python string!"
    sub2 = "an arg"
    
    a = "i am a %s" % sub1
    b = "i am a {0}".format(sub1)
    
    c = "with %(kwarg)s!" % {'kwarg':sub2}
    d = "with {kwarg}!".format(kwarg=sub2)
    
    print a    # "i am a python string!"
    print b    # "i am a python string!"
    print c    # "with an arg!"
    print d    # "with an arg!"
    
  2. Selanjutnya kapan pemformatan string terjadi dengan Python? Misalnya, jika tingkat pencatatan saya disetel ke TINGGI, saya masih akan menerima pukulan untuk melakukan hal berikut % operasi? Dan jika demikian, apakah ada cara untuk menghindari hal ini?

    log.debug("some debug info: %s" % some_info)
    

1178
2018-02-22 18:46


asal


Jawaban:


Untuk menjawab pertanyaan pertamamu ... .format sepertinya lebih canggih dalam banyak hal. Suatu hal yang menjengkelkan % juga bagaimana ia bisa mengambil variabel atau tuple. Anda akan berpikir hal berikut akan selalu berhasil:

"hi there %s" % name

namun, jika name kebetulan terjadi (1, 2, 3), itu akan melempar a TypeError. Untuk menjamin bahwa itu selalu dicetak, Anda harus melakukannya

"hi there %s" % (name,)   # supply the single argument as a single-item tuple

yang hanya jelek. .format tidak memiliki masalah itu. Juga dalam contoh kedua yang Anda berikan, .format Contohnya jauh lebih bersih mencari.

Kenapa kamu tidak menggunakannya?

  • tidak mengetahui tentang hal itu (saya sebelum membaca ini)
  • harus kompatibel dengan Python 2.5

Untuk menjawab pertanyaan kedua Anda, pemformatan string terjadi pada saat yang bersamaan dengan operasi lainnya - saat ekspresi pemformatan string dievaluasi. Dan Python, tidak menjadi bahasa yang malas, mengevaluasi ekspresi sebelum memanggil fungsi, jadi pada Anda log.debug contoh, ekspresi "some debug info: %s"%some_infopertama-tama akan mengevaluasi ke, mis. "some debug info: roflcopters are active", maka string itu akan diteruskan ke log.debug().


852
2018-02-22 18:49



Sesuatu yang operator modulo (%) tidak bisa lakukan, afaik:

tu = (12,45,22222,103,6)
print '{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu)

hasil

12 22222 45 22222 103 22222 6 22222

Sangat berguna.

Titik lain: format(), menjadi fungsi, dapat digunakan sebagai argumen dalam fungsi lain:

li = [12,45,78,784,2,69,1254,4785,984]
print map('the number is {}'.format,li)   

print

from datetime import datetime,timedelta

once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0)
delta = timedelta(days=13, hours=8,  minutes=20)

gen =(once_upon_a_time +x*delta for x in xrange(20))

print '\n'.join(map('{:%Y-%m-%d %H:%M:%S}'.format, gen))

Hasil dalam:

['the number is 12', 'the number is 45', 'the number is 78', 'the number is 784', 'the number is 2', 'the number is 69', 'the number is 1254', 'the number is 4785', 'the number is 984']

2010-07-01 12:00:00
2010-07-14 20:20:00
2010-07-28 04:40:00
2010-08-10 13:00:00
2010-08-23 21:20:00
2010-09-06 05:40:00
2010-09-19 14:00:00
2010-10-02 22:20:00
2010-10-16 06:40:00
2010-10-29 15:00:00
2010-11-11 23:20:00
2010-11-25 07:40:00
2010-12-08 16:00:00
2010-12-22 00:20:00
2011-01-04 08:40:00
2011-01-17 17:00:00
2011-01-31 01:20:00
2011-02-13 09:40:00
2011-02-26 18:00:00
2011-03-12 02:20:00

281
2018-06-13 20:20



Dengan asumsi Anda menggunakan Python logging modul, Anda dapat meneruskan argumen pemformatan string sebagai argumen ke .debug() metode daripada melakukan pemformatan sendiri:

log.debug("some debug info: %s", some_info)

yang menghindari melakukan pemformatan kecuali logger benar-benar mencatat sesuatu.


124
2018-02-22 19:21



Mulai Python 3.6 (2016) dapat Anda gunakan f-string untuk mengganti variabel:

>>> origin = "London"
>>> destination = "Paris"
>>> f"from {origin} to {destination}"
'from London to Paris'

Perhatikan f" awalan. Jika Anda mencoba ini dengan Python 3.5 atau sebelumnya, Anda akan mendapatkan SyntaxError.

Lihat https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings


88
2018-04-15 11:12



PEP 3101 mengusulkan penggantian % operator dengan pemformatan string tingkat lanjut yang baru di Python 3, di mana ini akan menjadi default.


54
2017-08-01 03:01



Tapi tolong hati-hati, baru sekarang saya telah menemukan satu masalah ketika mencoba untuk mengganti semua % dengan .format dalam kode yang ada: '{}'.format(unicode_string) akan mencoba untuk menyandikan unicode_string dan mungkin akan gagal.

Lihat saja log sesi interaktif Python ini:

Python 2.7.2 (default, Aug 27 2012, 19:52:55) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
; s='й'
; u=u'й'
; s
'\xd0\xb9'
; u
u'\u0439'

s hanyalah sebuah string (disebut 'byte array' di Python3) dan u adalah string Unicode (disebut 'string' dalam Python3):

; '%s' % s
'\xd0\xb9'
; '%s' % u
u'\u0439'

Saat Anda memberi objek Unicode sebagai parameter % operator itu akan menghasilkan string Unicode bahkan jika string aslinya tidak Unicode:

; '{}'.format(s)
'\xd0\xb9'
; '{}'.format(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0439' in position 0: ordinal not in range(256)

tetapi .format function akan menaikkan "UnicodeEncodeError":

; u'{}'.format(s)
u'\xd0\xb9'
; u'{}'.format(u)
u'\u0439'

dan itu akan bekerja dengan argumen Unicode denda hanya jika string asli adalah Unicode.

; '{}'.format(u'i')
'i'

atau jika argumen string dapat dikonversi menjadi string (disebut 'array byte')


51
2017-09-03 18:15



Namun keuntungan lain dari .format (yang saya tidak lihat di jawaban): dapat mengambil properti objek.

In [12]: class A(object):
   ....:     def __init__(self, x, y):
   ....:         self.x = x
   ....:         self.y = y
   ....:         

In [13]: a = A(2,3)

In [14]: 'x is {0.x}, y is {0.y}'.format(a)
Out[14]: 'x is 2, y is 3'

Atau, sebagai argumen kata kunci:

In [15]: 'x is {a.x}, y is {a.y}'.format(a=a)
Out[15]: 'x is 2, y is 3'

Ini tidak mungkin dengan % sejauh yang saya tahu.


33
2017-12-04 18:33



Seperti yang saya temukan hari ini, cara lama memformat string melalui % tidak mendukung Decimal, Modul Python untuk titik desimal tetap dan aritmatika floating point, di luar kotak.

Contoh (menggunakan Python 3.3.5):

#!/usr/bin/env python3

from decimal import *

getcontext().prec = 50
d = Decimal('3.12375239e-24') # no magic number, I rather produced it by banging my head on my keyboard

print('%.50f' % d)
print('{0:.50f}'.format(d))

Keluaran:

0,00000000000000000000000312375239000000009907464850   0,00000000000000000000000312375239000000000000000000

Mungkin memang ada pekerjaan tetapi Anda masih mungkin mempertimbangkan untuk menggunakan format() metode segera.


27
2018-05-13 17:10



% memberikan kinerja yang lebih baik daripada format dari pengujian saya.

Kode pengujian:

Python 2.7.2:

import timeit
print 'format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')")
print '%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')")

Hasil:

> format: 0.470329046249
> %: 0.357107877731

Python 3.5.2

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))

Hasil

> format: 0.5864730989560485
> %: 0.013593495357781649

Terlihat di Python2, perbedaannya kecil sedangkan di Python3, % jauh lebih cepat daripada format.

Terima kasih @Chris Cogdon untuk kode contoh.


20
2018-06-13 18:43