Pemformatan string:% vs. .format

1349

Python 2.6 memperkenalkan str.format()metode ini dengan sintaks yang sedikit berbeda dari %operator yang ada . 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 dalam Python? Misalnya, jika tingkat logging saya diatur ke TINGGI akankah saya masih terpukul untuk melakukan %operasi berikut ? Dan jika demikian, adakah cara untuk menghindari ini?

    log.debug("some debug info: %s" % some_info)
NorthIsUp
sumber
2
Untuk pemula: Ini adalah tutorial yang sangat bagus yang mengajarkan kedua gaya. Saya pribadi menggunakan %gaya lama lebih sering, karena jika Anda tidak memerlukan peningkatan kemampuan format()gaya, %gaya sering jauh lebih nyaman.
Lutz Prechelt
2
Untuk referensi: Python 3 dokumentasi untuk baru format()gaya format dan lebih tua %gaya format berbasis .
Lutz Prechelt
1
Untuk menjawab pertanyaan kedua Anda, sejak 3,2 Anda dapat menggunakan format {} jika Anda menggunakan formatter khusus (lihat docs.python.org/3/library/logging.html#logging.Formatter )
yanjost

Jawaban:

953

Untuk menjawab pertanyaan pertama Anda ... .formatsepertinya lebih canggih dalam banyak hal. Suatu hal yang menjengkelkan tentang %juga bagaimana bisa mengambil variabel atau tuple. Anda akan berpikir hal berikut akan selalu berhasil:

"hi there %s" % name

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

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

yang hanya jelek. .formattidak memiliki masalah itu. Juga dalam contoh kedua yang Anda berikan, .formatcontohnya tampak jauh lebih bersih.

Mengapa Anda tidak menggunakannya?

  • tidak mengetahuinya (saya sebelum membaca ini)
  • harus kompatibel dengan Python 2.5

Untuk menjawab pertanyaan kedua Anda, pemformatan string terjadi pada saat yang sama dengan operasi lainnya - ketika ekspresi pemformatan string dievaluasi. Dan Python, bukan menjadi bahasa yang malas, mengevaluasi ekspresi sebelum memanggil fungsi, jadi dalam log.debugcontoh Anda , ekspresi "some debug info: %s"%some_infopertama akan mengevaluasi, misalnya "some debug info: roflcopters are active", kemudian string itu akan diteruskan ke log.debug().

Claudiu
sumber
113
bagaimana dengan"%(a)s, %(a)s" % {'a':'test'}
ted
128
Perhatikan bahwa Anda akan membuang waktu untuk log.debug("something: %s" % x)tetapi tidak untuk log.debug("something: %s", x) Pemformatan string akan ditangani dalam metode dan Anda tidak akan mendapatkan kinerja yang baik jika itu tidak akan dicatat. Seperti biasa, Python mengantisipasi kebutuhan Anda =)
darkfeline
63
ted: itu hack yang terlihat lebih buruk untuk melakukan hal yang sama '{0}, {0}'.format('test').
domba terbang
19
Intinya adalah: Argumen yang berulang bahwa sintaks baru memungkinkan pemesanan ulang item adalah titik diperdebatkan: Anda dapat melakukan hal yang sama dengan sintaks lama. Kebanyakan orang tidak tahu bahwa ini sebenarnya sudah didefinisikan dalam Ansi C99 Std! Lihat salinan terbaru man sprintfdan pelajari tentang $notasi di dalam %placeholder
cfi
29
@ cfi: Jika Anda bermaksud sesuatu seperti, printf("%2$d", 1, 3)untuk mencetak "3", itu ditentukan dalam POSIX, bukan C99. Halaman manual yang Anda referensikan mencatat, "Standar C99 tidak termasuk gaya menggunakan '$' ...".
Thanatos
307

Sesuatu yang tidak bisa dilakukan operator modulo (%), 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.

Poin lain:, format()sebagai 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
eyquem
sumber
17
Anda dapat menggunakan pemformatan gaya lama mapsemudah memformat. map('some_format_string_%s'.__mod__, some_iterable)
agf
3
@ cfi: tolong buktikan bahwa Anda benar dengan menulis ulang contoh di atas dalam C99
MarcH
9
@ Markc: printf("%2$s %1$s\n", "One", "Two");dikompilasi dengan gcc -std=c99 test.c -o test, hasilnya Two One. Tapi saya berdiri dikoreksi: Ini sebenarnya adalah ekstensi POSIX dan bukan C. Saya tidak dapat menemukannya lagi dalam standar C / C ++, di mana saya pikir saya telah melihatnya. Kode berfungsi bahkan dengan bendera std 'c90'. sprintfhalaman manual . Ini tidak mencantumkannya, tetapi memungkinkan lib untuk mengimplementasikan superset. Argumen asli saya masih valid, diganti CdenganPosix
cfi
8
Komentar pertama saya di sini, tidak berlaku untuk jawaban ini. Saya menyesal ungkapan itu. Dalam Python kita tidak bisa menggunakan operator modulo %untuk memesan kembali placeholder. Saya masih ingin tidak menghapus komentar pertama itu demi konsistensi komentar di sini. Saya minta maaf karena telah melampiaskan kemarahan saya di sini. Hal ini diarahkan terhadap pernyataan yang sering dibuat bahwa sintaksis lama tidak akan mengizinkan hal ini. Alih-alih membuat sintaks yang sama sekali baru, kita bisa memperkenalkan ekstensi std Posix. Kita bisa memiliki keduanya.
cfi
17
'modulo' mengacu pada operator yang mengevaluasi sisa setelah pembagian. dalam hal ini tanda persen bukan operator modulo.
Octopus
148

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

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

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

Wooble
sumber
10
Ini adalah beberapa info berguna yang baru saja saya pelajari sekarang. Sayang tidak memiliki pertanyaan sendiri karena tampaknya terpisah dengan pertanyaan utama. Sayang OP tidak membagi pertanyaannya menjadi dua pertanyaan terpisah.
snth
12
Anda dapat menggunakan format dict seperti ini: log.debug("some debug info: %(this)s and %(that)s", dict(this='Tom', that='Jerry')) Namun, Anda tidak dapat menggunakan .format()sintaks gaya baru di sini, bahkan dalam Python 3.3, yang memalukan.
Cito
15
@Cito: Lihat ini: plumberjack.blogspot.co.uk/2010/10/...
Vinay Sajip
26
Manfaat utama dari ini bukan kinerja (melakukan interpolasi string akan lebih cepat dibandingkan dengan apa pun yang Anda lakukan dengan output dari logging, misalnya menampilkan di terminal, menyimpan ke disk) Ini adalah bahwa jika Anda memiliki agregator logging, itu dapat memberi tahu Anda "Anda mendapatkan 12 contoh pesan kesalahan ini", bahkan jika mereka semua memiliki nilai 'some_info' yang berbeda. Jika pemformatan string dilakukan sebelum meneruskan string ke log.debug, maka ini tidak mungkin. Agregator hanya dapat mengatakan "Anda memiliki 12 pesan log yang berbeda"
Jonathan Hartley
7
Jika Anda khawatir tentang kinerja, gunakan sintaks literal {} alih-alih instantiasi kelas (dict) kelas: doughellmann.com/2012/11/…
trojjer
119

Pada Python 3.6 (2016) Anda bisa menggunakan f-string untuk mengganti variabel:

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

Perhatikan f"awalannya. 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

Kolonel Panic
sumber
1
Ini tidak menjawab pertanyaan. Jawaban lain yang menyebutkan f-string setidaknya berbicara tentang kinerja: stackoverflow.com/a/51167833/7851470
Georgy
60

PEP 3101 mengusulkan penggantian %operator dengan pemformatan string canggih baru dalam Python 3, di mana ia akan menjadi default.

Brainstorm
sumber
14
Tidak Benar: "Kompatibilitas mundur dapat dipertahankan dengan membiarkan mekanisme yang ada di tempatnya."; tentu saja, .formattidak akan mengganti % pemformatan string.
Tobias
12
Tidak, postulat BrainStorms benar: "dimaksudkan sebagai pengganti '%' yang ada". Kutipan Tobias berarti kedua sistem akan hidup berdampingan untuk beberapa waktu. RTFPEP
phobie
54

Tapi harap berhati-hati, baru saja saya menemukan satu masalah ketika mencoba mengganti semua %dengan .formatkode yang ada: '{}'.format(unicode_string)akan mencoba menyandikan unicode_string dan mungkin akan gagal.

Lihat 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'

shanya string (disebut 'byte array' di Python3) dan umerupakan string Unicode (disebut 'string' dalam Python3):

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

Ketika Anda memberikan objek Unicode sebagai parameter kepada %operator, ia akan menghasilkan string Unicode bahkan jika string asli bukan 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 .formatfungsinya akan memunculkan "UnicodeEncodeError":

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

dan itu akan bekerja dengan argumen Unicode baik-baik saja jika string asli adalah Unicode.

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

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

wobmene
sumber
12
Tidak ada alasan untuk mengubah kode kerja kecuali fitur tambahan dari formatmetode baru benar-benar diperlukan ...
Tobias
benar-benar setuju dengan Anda, Tobias, tetapi kadang-kadang diperlukan saat memutakhirkan ke versi Python yang lebih baru
wobmene
2
Contohnya? AFAIK, tidak pernah dibutuhkan; Saya tidak menganggap kemungkinan %interpolasi string akan hilang.
Tobias
4
Saya menganggap fungsi .format () lebih aman daripada% untuk string. Seringkali saya melihat kesalahan pemula seperti ini "p1=%s p2=%d" % "abc", 2atau "p1=%s p2=%s" % (tuple_p1_p2,). Anda mungkin berpikir itu adalah kesalahan pembuat kode, tetapi saya pikir itu hanya sintaks yang aneh aneh yang terlihat bagus untuk quicky-scriptie tetapi buruk untuk kode produksi.
wobmene
3
Tapi saya tidak suka sintaks dari .format (), saya akan lebih bahagia dengan baik tua %s, %02dseperti "p1=%s p2=%02d".format("abc", 2). Saya menyalahkan mereka yang menemukan dan menyetujui format kurung kurawal yang mengharuskan Anda untuk melarikan diri dari mereka {{}}dan terlihat imho jelek.
wobmene
35

Namun keuntungan lain dari .format(yang saya tidak melihat dalam 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.

matiasg
sumber
4
Ini terlihat lebih tidak dapat dibaca daripada yang diperlukan dibandingkan dengan yang setara 'x is {0}, y is {1}'.format(a.x, a.y). Seharusnya hanya digunakan saat a.xoperasi sangat mahal.
dtheodor
13
@dtheodor Dengan tweak untuk menggunakan argumen kata kunci bukan argumen posisional ... 'x is {a.x}, y is {a.y}'.format(a=a). Lebih mudah dibaca daripada kedua contoh.
CivFan
1
@CivFan Atau, jika Anda memiliki lebih dari satu objek,'x is {a.x}, y is {a.y}'.format(**vars())
Jack
1
Juga perhatikan satu ini dengan cara yang sama: '{foo[bar]}'.format(foo={'bar': 'baz'}).
Antoine Pinsard
3
Ini sangat berguna untuk aplikasi yang menghadapi pelanggan, di mana aplikasi Anda memasok sekumpulan opsi format standar dengan string format yang disediakan pengguna. Saya menggunakan ini sepanjang waktu. File konfigurasi, misalnya, akan memiliki beberapa properti "messagestring", yang dapat disediakan oleh pengguna Your order, number {order[number]} was processed at {now:%Y-%m-%d %H:%M:%S}, will be ready at about {order[eta]:%H:%M:%S}atau apa pun yang mereka inginkan. Ini jauh lebih bersih daripada mencoba menawarkan fungsionalitas yang sama dengan formatter lama. Itu membuat string format yang disediakan pengguna jauh lebih kuat.
Taywee
35

%memberikan kinerja yang lebih baik daripada formatdari tes saya.

Kode uji:

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

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

Terima kasih @Chris Cogdon untuk kode sampel.

Edit 1:

Diuji lagi dengan Python 3.7.2 pada Juli 2019.

Hasil:

> format: 0.86600608
> %: 0.630180146

Tidak banyak perbedaan. Saya kira Python membaik secara bertahap.

Edit 2:

Setelah seseorang menyebutkan f-string python 3 dalam komentar, saya melakukan tes untuk kode berikut di bawah python 3.7.2:

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

Hasil:

format: 0.8331376779999999
%: 0.6314778750000001
f-string: 0.766649943

Tampaknya f-string masih lebih lambat daripada %tetapi lebih baik daripada format.

lcltj
sumber
42
Sebagai gantinya, str.formatmemberikan lebih banyak fungsionalitas (misalnya pemformatan khusus tipe '{0:%Y-%m-%d}'.format(datetime.datetime.utcnow())). Kinerja tidak dapat menjadi persyaratan mutlak dari semua pekerjaan. Gunakan alat yang tepat untuk pekerjaan itu.
minhee
36
"Optimalisasi prematur adalah akar dari semua kejahatan" atau begitulah kata Donald Knuth ...
Yatharth Agarwal
22
Menempel dengan skema pemformatan yang terkenal (selama itu sesuai dengan kebutuhan, yang dilakukannya di sebagian besar kasus), dan yang dua kali lebih cepat, bukanlah "optimasi prematur" tetapi cukup masuk akal. BTW, %operator memungkinkan untuk menggunakan kembali printfpengetahuan; interpolasi kamus adalah perluasan prinsip yang sangat sederhana.
Tobias
5
Saya benar-benar mengalami yang sebaliknya dalam satu situasi. Pemformatan gaya baru lebih cepat. Bisakah Anda memberikan kode tes yang Anda gunakan?
David Sanders
8
Sepertinya posting yang terbuang sia-sia tanpa contoh atau alasan, hanya klaim.
kevr
31

Seperti yang saya temukan hari ini, cara lama memformat string melalui %tidak mendukungDecimal , modul Python untuk titik tetap desimal dan aritmatika titik mengambang, 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,0000000000000000000000031237523900000000999907464850 0,000000000000000000000000031237523900000000000000000000

Tentunya mungkin ada penyelesaian tetapi Anda masih dapat segera mempertimbangkan untuk menggunakan format()metode ini.

balu
sumber
1
Itu mungkin karena panggilan pemformatan gaya baru str(d)sebelum memperluas parameter, sedangkan pemformatan gaya lama mungkin memanggil float(d)terlebih dahulu.
David Sanders
3
Anda akan berpikir begitu, tetapi str(d)kembali "3.12375239e-24", tidak"0.00000000000000000000000312375239000000000000000000"
Jack
18

Jika python Anda> = 3.6, literal berformat F-string adalah teman baru Anda.

Ini lebih sederhana, bersih, dan kinerjanya lebih baik.

In [1]: params=['Hello', 'adam', 42]

In [2]: %timeit "%s %s, the answer to everything is %d."%(params[0],params[1],params[2])
448 ns ± 1.48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [3]: %timeit "{} {}, the answer to everything is {}.".format(*params)
449 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit f"{params[0]} {params[1]}, the answer to everything is {params[2]}."
12.7 ns ± 0.0129 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
zhengcao
sumber
15

Sebagai catatan tambahan, Anda tidak perlu melakukan hit kinerja untuk menggunakan pemformatan gaya baru dengan pencatatan. Anda dapat melewati objek apapun untuk logging.debug, logging.info, dll yang mengimplementasikan dengan __str__metode magic. Ketika modul logging telah memutuskan bahwa ia harus memancarkan objek pesan Anda (apa pun itu), ia memanggil str(message_object)sebelum melakukannya. Jadi Anda bisa melakukan sesuatu seperti ini:

import logging


class NewStyleLogMessage(object):
    def __init__(self, message, *args, **kwargs):
        self.message = message
        self.args = args
        self.kwargs = kwargs

    def __str__(self):
        args = (i() if callable(i) else i for i in self.args)
        kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items())

        return self.message.format(*args, **kwargs)

N = NewStyleLogMessage

# Neither one of these messages are formatted (or calculated) until they're
# needed

# Emits "Lazily formatted log entry: 123 foo" in log
logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo'))


def expensive_func():
    # Do something that takes a long time...
    return 'foo'

# Emits "Expensive log entry: foo" in log
logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func))

Ini semua dijelaskan dalam dokumentasi Python 3 ( https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ). Namun, ini juga akan bekerja dengan Python 2.6 ( https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages ).

Salah satu keuntungan menggunakan teknik ini, selain fakta bahwa itu adalah format-agnostik, adalah memungkinkan untuk nilai-nilai malas misalnya fungsi di expensive_funcatas. Ini memberikan alternatif yang lebih elegan untuk saran yang diberikan dalam dokumen Python di sini: https://docs.python.org/2.6/library/logging.html#optimization .

David Sanders
sumber
2
Saya berharap saya bisa lebih mengangkat ini. Hal ini memungkinkan logging dengan formattanpa kinerja hit - melakukannya dengan menimpa __str__tepat seperti loggingyang dirancang untuk - mempersingkat pemanggilan fungsi ke satu huruf ( N) yang terasa sangat mirip dengan beberapa cara standar untuk mendefinisikan string - DAN memungkinkan untuk malas pemanggilan fungsi. Terima kasih! +1
CivFan
2
Apakah ini berbeda hasilnya dengan menggunakan logging.Formatter(style='{')parameter?
davidA
10

Satu situasi di mana %dapat membantu adalah ketika Anda memformat ekspresi regex. Sebagai contoh,

'{type_names} [a-z]{2}'.format(type_names='triangle|square')

menimbulkan IndexError. Dalam situasi ini, Anda dapat menggunakan:

'%(type_names)s [a-z]{2}' % {'type_names': 'triangle|square'}

Ini menghindari penulisan regex sebagai '{type_names} [a-z]{{2}}'. Ini bisa berguna ketika Anda memiliki dua regex, di mana satu digunakan sendiri tanpa format, tetapi gabungan keduanya diformat.

Jorge Leitao
sumber
3
Atau gunakan saja '{type_names} [a-z]{{2}}'.format(type_names='triangle|square'). Ini seperti mengatakan .format()dapat membantu ketika menggunakan string yang sudah mengandung karakter persen. Tentu. Anda harus melarikan diri dari mereka.
Alfe
1
@Alfe Anda benar, dan itulah sebabnya jawabannya dimulai dengan "One situation where % may help is when you are formatting regex expressions."Secara khusus, anggaplah a=r"[a-z]{2}"potongan regex yang akan Anda gunakan dalam dua ekspresi akhir yang berbeda (misalnya c1 = b + adan c2 = a). Asumsikan yang c1perlu formatdiedit (mis. bPerlu diformat runtime), tetapi c2tidak. Maka Anda perlu a=r"[a-z]{2}"untuk c2dan a=r"[a-z]{{2}}"untuk c1.format(...).
Jorge Leitao
7

Saya akan menambahkan bahwa sejak versi 3.6, kita dapat menggunakan fstrings seperti berikut

foo = "john"
bar = "smith"
print(f"My name is {foo} {bar}")

Yang memberi

Nama saya john smith

Semuanya dikonversi menjadi string

mylist = ["foo", "bar"]
print(f"mylist = {mylist}")

Hasil:

mylist = ['foo', 'bar']

Anda dapat melewati fungsi, seperti dalam metode format lain

print(f'Hello, here is the date : {time.strftime("%d/%m/%Y")}')

Memberi misalnya

Halo, ini tanggalnya: 16/04/2018

Sylvan LE DEUNFF
sumber
4

Untuk versi python> = 3.6 (lihat PEP 498 )

s1='albha'
s2='beta'

f'{s1}{s2:>10}'

#output
'albha      beta'
Roushan
sumber
2

Python 3.6.7 komparatif:

#!/usr/bin/env python
import timeit

def time_it(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{0:.10f} seconds".format(t1 - t0))
    return wrapper


@time_it
def new_new_format(s):
    print("new_new_format:", f"{s[0]} {s[1]} {s[2]} {s[3]} {s[4]}")


@time_it
def new_format(s):
    print("new_format:", "{0} {1} {2} {3} {4}".format(*s))


@time_it
def old_format(s):
    print("old_format:", "%s %s %s %s %s" % s)


def main():
    samples = (("uno", "dos", "tres", "cuatro", "cinco"), (1,2,3,4,5), (1.1, 2.1, 3.1, 4.1, 5.1), ("uno", 2, 3.14, "cuatro", 5.5),) 
    for s in samples:
        new_new_format(s)
        new_format(s)
        old_format(s)
        print("-----")


if __name__ == '__main__':
    main()

Keluaran:

new_new_format: uno dos tres cuatro cinco
0.0000170280 seconds
new_format: uno dos tres cuatro cinco
0.0000046750 seconds
old_format: uno dos tres cuatro cinco
0.0000034820 seconds
-----
new_new_format: 1 2 3 4 5
0.0000043980 seconds
new_format: 1 2 3 4 5
0.0000062590 seconds
old_format: 1 2 3 4 5
0.0000041730 seconds
-----
new_new_format: 1.1 2.1 3.1 4.1 5.1
0.0000092650 seconds
new_format: 1.1 2.1 3.1 4.1 5.1
0.0000055340 seconds
old_format: 1.1 2.1 3.1 4.1 5.1
0.0000052130 seconds
-----
new_new_format: uno 2 3.14 cuatro 5.5
0.0000053380 seconds
new_format: uno 2 3.14 cuatro 5.5
0.0000047570 seconds
old_format: uno 2 3.14 cuatro 5.5
0.0000045320 seconds
-----
Felix Martinez
sumber
3
Anda harus menjalankan setiap contoh beberapa kali, satu kali saja mungkin menyesatkan mis. Sistem operasi mungkin sibuk sehingga eksekusi kode Anda tertunda. lihat dokumen: docs.python.org/3/library/timeit.html . (avatar yang bagus, Guybrush!)
jake77
1

Tetapi satu hal adalah itu juga jika Anda memiliki kurung kurawal, tidak akan berfungsi untuk format tetapi %akan berfungsi.

Contoh:

>>> '{{0}, {1}}'.format(1,2)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    '{{0}, {1}}'.format(1,2)
ValueError: Single '}' encountered in format string
>>> '{%s, %s}'%(1,2)
'{1, 2}'
>>> 
U10-Maju
sumber
2
Anda bisa melakukan ini, tetapi saya setuju formatnya luar biasa '{{{0}, {1}}}' (1, 2)
Sylvan LE DEUNFF
Kata kunci kurung kurawal berfungsi dan cukup bagus.
CivFan