„Python“ eilutės formatavimas:% vs

Python 2.6 pristatė str.format() metodą su šiek tiek kitokia sintaksė iš esamo % operatoriaus. Kas yra geresnė ir kokiose situacijose?

  • Šis metodas naudoja kiekvieną metodą ir turi tą patį rezultatą, todėl koks skirtumas?

     #!/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!" 
  • Be to, kada pythone vyksta eilutės formatavimas? Pvz., Jei mano registravimo lygis yra nustatytas į HIGH, ar vis tiek pasieksiu, kad atliktumėte%% operaciją? Ir jei taip, ar tai yra būdas išvengti?

     log.debug("some debug info: %s" % some_info) 
1226
22 февр. „ NorthIsUp“ nustatė vasario 22 d 2011-02-22 21:46 '11, 21:46, 2011-02-22 21:46
@ 16 atsakymų

Norint atsakyti į pirmąjį klausimą, .format tiesiog atrodo daug sudėtingesnis. Kenkiantis dalykas apie % pat % tai, kaip jis gali būti kintamasis ar paketas. Galbūt manote, kad šie veiksmai visada veiks:

 "hi there %s" % name 

bet jei name yra (1, 2, 3) , jis išnyks TypeError . Kad įsitikintumėte, jog jis visada spausdinamas, turėsite tai padaryti

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

kuris yra tik bjaurus. .format neturi tokių problemų. Be to, antrajame jūsų nurodytame pavyzdyje .format pavyzdys atrodo švaresnis.

Kodėl nenaudojate?

  • nežinant (I, prieš skaitydamas šį)
  • Turi būti suderinama su Python 2.5

Norėdami atsakyti į antrąjį klausimą, eilutės formatavimas vyksta kartu su bet kuria kita operacija - vertinant eilutės formatavimo išraišką. „Python“, kuri nėra tingi kalba, vertina išraiškas prieš skambindama funkcijoms, todėl jūsų pavyzdyje log.debug frazė "some debug info: %s"%some_info , pvz., "some debug info: roflcopters are active" , tada ši eilutė bus perduotas log.debug() .

882
22 февр. Claudiu atsakė vasario 22 d. 2011-02-22 21:49 '11 prie 21:49 2011-02-22 21:49

Kažkas, kad modulis (%), afaik operatorius negali atlikti:

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

rezultatas

 12 22222 45 22222 103 22222 6 22222 

Labai naudinga.

border=0

Kitas taškas: format() , kuris yra funkcija, gali būti naudojamas kaip argumentas kitose funkcijose:

 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)) 

Rezultatai:

 ['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 
287
13 июня '11 в 23:20 2011-06-13 23:20 atsakymą pateikė „ eyquem“ birželio 13 d. 11 val. 23:20 2011-06-13 23:20

Darant prielaidą, kad naudojate „Python“ logging modulį, galite perduoti eilutės formatavimo argumentus kaip argumentus .debug() metodui, o ne formatuodami save:

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

kuris vengia formatavimo, jei įrašymo įrenginys nieko neįrašo.

128
22 февр. Wooble paskelbė vasario 22 dieną 2011-02-22 22:21 '11, 10:21 val. 2011-02-22 22:21

Nuo „Python 3.6“ (2016) galite keisti kintamuosius f-eilutes :

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

Atkreipkite dėmesį į f" prefiksą. Jei bandysite tai„ Python 3.5 “ar anksčiau, gausite„ SyntaxError .

Žr. Https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings

97
15 апр. atsakymą pateikė pulkininkas Panicas balandžio 15 d 2016-04-15 14:12 '16 at 14:12 pm 2016-04-15 14:12

PEP 3101 siūlo pakeisti % pareiškimą su nauju išplėstiniu stygų formatu Python 3, kur jis bus naudojamas pagal nutylėjimą.

55
01 авг. Atsakymas duotas BrainStorm 01 rug. 2011-08-01 06:01 2011-11-08 06:01 06:01

Bet būkite atsargūs, tik dabar radau vieną problemą bandant pakeisti visus % su .format esamame kode: '{}'.format(unicode_string) bandys koduoti unicode_string ir tikriausiai nepavyks.

Peržiūrėkite šį interaktyvių „Python“ sesijų žurnalą:

 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 yra tik eilutė (Python3 vadinama „baitų masyvu“) ir u yra Unicode eilutė (vadinama „string“ Python3):

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

Kai nurodote Unicode objektą kaip % operatoriaus parametrą, jis grąžina Unicode eilutę, net jei šaltinio eilutė nebuvo 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) 

tačiau .format funkcija padidins „UnicodeEncodeError“:

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

ir jis veiks su Unicode argumentu bauda tik tuo atveju, jei šaltinio eilutė buvo Unicode.

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

arba argumentų eilutė gali būti konvertuojama į eilutę (vadinamasis „baitų masyvas“)

51
03 сент. atsakymas pateikiamas rslnx 03 sep . 2012-09-03 21:15 '12 - 21:15 2012-09-03 21:15

Kitas .format privalumas (kurį nematau atsakymuose) yra tai, kad jis gali paimti objekto savybes.

 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' 

Arba, kaip raktinio žodžio argumentas:

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

Tai neįmanoma su % , kiek galiu pasakyti.

33
04 дек. atsakymas duotas matiasg 04 dec. 2014-12-04 21:33 '14, 21:33 2014-12-04 21:33

Kaip šiandien atradau, senas būdas formuoti eilutes per % nepalaiko Decimal , Python modulio dešimtainiams fiksuotiems taškams ir slankiojo kablelio aritmetikos, iš dėžutės.

Pavyzdys (naudojant 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)) 

Išvada:

0.000000000000000000000312375239000000009907464850 0.00000000000000000000031237523900000000000000000000

Žinoma, gali kilti problemų, tačiau jūs vis tiek galite naudoti format() metodą.

28
13 мая '14 в 20:10 2014-05-13 20:10 atsakymas pateikiamas balu gegužės 13 d., 14 val. 20:10 2014-05-13 20:10

% suteikia geresnį našumą nei mano bandymo format .

Bandymo kodas:

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')") 

Rezultatas:

 > 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')")) 

Rezultatas

 > format: 0.5864730989560485 > %: 0.013593495357781649 

Jis atrodo Python2, skirtumas yra mažas, o Python3 % daug greičiau nei format .

Ačiū @ Chris Cogdon už mėginio kodą.

24
13 июня '11 в 21:43 2011-06-13 21:43 atsakymas pateikiamas lcltj birželio 13 d. 11 val. 21:43 2011-06-13 21:43

Kaip šalutinę pastabą, jums nereikia imtis rezultatų, kad galėtumėte naudoti naują formatavimo stilių su registravimu. Galite perduoti bet kurį objektą į logging.debug , logging.info ir tt, kuris įgyvendina __str__ magijos metodą. Kai registravimo modulis nusprendžia, kad jis turėtų skleisti jūsų pranešimo objektą (nesvarbu, koks jis yra), prieš tai jis vadina str(message_object) . Taigi galite tai padaryti:

 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)) 

Visa tai aprašyta Python 3 dokumentuose ( https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ). Tačiau jis veiks su „Python 2.6“ ( https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages ).

Vienas iš šio metodo privalumų, be to, kad jis yra formavimo stiliaus agnostikas, yra tai, kad jis leidžia, pavyzdžiui, tingus. veikia expensive_func . Tai suteikia elegantiškesnę alternatyvą patarimams, pateikiamiems „Python“ dokumentuose: https://docs.python.org/2.6/library/logging.html#optimization .

14
21 авг. David Sanders atsakymas rugpjūčio 21 d 2014-08-21 21:00 '14 21:00 val. 2014-08-21 21:00

Viena situacija, kai % gali padėti, kai formatuojate reguliarias išraiškas. Pavyzdžiui

 '{type_names} [az]{2}'.format(type_names='triangle|square') 

sukelia „ IndexError . Tokiu atveju galite naudoti:

 '%(type_names)s [az]{2}' % {'type_names': 'triangle|square'} 

Taip išvengsite rašyti įprastą išraišką, pvz., '{type_names} [az]{{2}}' . Tai gali būti naudinga, kai turite dvi reguliariąsias išraiškas, kuriose vienas naudojamas be formato, bet suformatuotas abiejų failų susiejimas.

8
09 апр. Jorge Leitão atsakymas 09 Bal 2015-04-09 23:41 '15, 23:41 pm 2015-04-09 23:41

Jei jūsų python> = 3.6, suformatuotas F-string literal yra jūsų naujas draugas.

Tai paprastesnis, švaresnis ir geresnis našumas.

 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) 
5
04 июля '18 в 10:13 2018-07-04 10:13 atsakymas pateikiamas zhengcao liepos 04-18 dienomis 10:13 2018-07-04 10:13

Norėčiau pridurti, kad nuo 3.6 versijos galime naudoti tekstilę, kaip parodyta žemiau

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

Kas suteikia

Mano vardas yra John Smith

Viskas konvertuota į eilutes

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

Rezultatas:

mylist = ['foo', 'bar']

Galite perduoti funkciją, kaip ir kituose formatuose.

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

Pavyzdžiui, teikimas

Sveiki, čia yra data: 16/04/2018

3
16 апр. Sylvan LE DEUNFF atsakymas, pateiktas balandžio 16 d 2018-04-16 17:42 '18 at 5:42 pm 2018-04-16 17:42

Python versijai> = 3.6 (žr. PEP 498 )

 s1='albha' s2='beta' f'{s1}{s2:>10}' #output 'albha beta' 
2
15 февр. Atsakymą pateikė Roushan vasario 15 d. 2018-02-15 01:42 '18 at 1:42 2018-02-15 01:42

Tačiau vienas dalykas yra tai, kad jei turite įdėtus petnešos, jie neveiks formatu, tačiau % veiks.

Pavyzdys:

 >>> '{{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}' >>> 
1
25 авг. atsakymas pateikiamas U9-Forward 25 rug. 2018-08-25 04:08 '18, 04:08 2018-08-25 04:08

Python 3.6.7 lyginamasis:

 #!/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() 

Išeiti:

 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 ----- 
0
05 февр. atsakymą pateikė Felix Martinez 05 vasaris. 2019-02-05 12:56 '19 , 12:56 pm 2019-02-05 12:56