स्ट्रिंग प्रारूपण:% बनाम .फॉर्मट


1348

पायथन 2.6 ने str.format()मौजूदा %ऑपरेटर से थोड़ा अलग सिंटैक्स के साथ विधि पेश की । कौन सा बेहतर है और किन स्थितियों के लिए है?

  1. निम्नलिखित प्रत्येक विधि का उपयोग करता है और इसका परिणाम समान होता है, इसलिए अंतर क्या है?

    #!/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. इसके अलावा जब पायथन में स्ट्रिंग स्वरूपण होता है? उदाहरण के लिए, यदि मेरा लॉगिंग स्तर हाई पर सेट है, तो क्या मैं अभी भी निम्नलिखित %ऑपरेशन करने के लिए एक हिट ले जाऊंगा? और यदि हां, तो क्या इससे बचने का कोई तरीका है?

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


2
शुरुआती लोगों के लिए: यहाँ एक बहुत अच्छा ट्यूटोरियल है जो दोनों शैलियों को सिखाता है। मैं व्यक्तिगत रूप से %अधिक बार पुरानी शैली का उपयोग करता हूं , क्योंकि यदि आपको format()शैली की बेहतर क्षमताओं की आवश्यकता नहीं है, तो %शैली अक्सर बहुत अधिक सुविधाजनक होती है।
लुत्ज प्रेक्लेट

2
संदर्भ के लिए: के लिए अजगर 3 प्रलेखन नए format()स्वरूपण शैली और पुराने %आधारित स्वरूपण शैली
लुत्ज प्रेचल


1
अपने दूसरे प्रश्न का उत्तर देने के लिए, 3.2 के बाद से आप {} प्रारूप का उपयोग कर सकते हैं यदि आप एक कस्टम फ़ॉर्मेटर का उपयोग करते हैं (देखें docs.python.org/3/library/log.html#logging.Formatter )
yanjost

जवाबों:


953

अपने पहले प्रश्न का उत्तर देने के लिए ... .formatबस कई तरीकों से अधिक परिष्कृत लगता है। इसके बारे %में एक कष्टप्रद बात यह भी है कि यह कैसे या तो एक चर या टपल ले सकता है। आपको लगता है कि निम्नलिखित हमेशा काम करेंगे:

"hi there %s" % name

अभी तक, अगर nameऐसा होता है , तो (1, 2, 3)यह एक फेंक देगा TypeError। यह गारंटी देने के लिए कि यह हमेशा प्रिंट करता है, आपको करना होगा

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

जो बदसूरत है। .formatउन मुद्दों नहीं है। इसके अलावा आपने जो दूसरा उदाहरण दिया है, वह .formatउदाहरण बहुत साफ लग रहा है।

आप इसका उपयोग क्यों नहीं करेंगे?

  • इसके बारे में नहीं पता (मुझे यह पढ़ने से पहले)
  • पायथन 2.5 के साथ संगत होना

आपके दूसरे प्रश्न का उत्तर देने के लिए, स्ट्रिंग फॉर्मेटिंग किसी भी अन्य ऑपरेशन की तरह ही होती है - जब स्ट्रिंग फॉर्मेटिंग अभिव्यक्ति का मूल्यांकन किया जाता है। और पायथन, एक आलसी भाषा नहीं होने से, कॉलिंग फ़ंक्शन से पहले भावों का मूल्यांकन करता है, इसलिए आपके log.debugउदाहरण में, अभिव्यक्ति "some debug info: %s"%some_infoपहले मूल्यांकन करेगी, जैसे "some debug info: roflcopters are active", फिर उस स्ट्रिंग को पास किया जाएगा log.debug()


113
क्या बारे में"%(a)s, %(a)s" % {'a':'test'}
ted

128
ध्यान दें कि आप समय बर्बाद करेंगे, log.debug("something: %s" % x)लेकिन log.debug("something: %s", x) स्ट्रिंग स्वरूपण के लिए विधि में संभाला नहीं जाएगा और अगर यह लॉग नहीं होगा, तो आपको प्रदर्शन हिट नहीं मिलेगा। हमेशा की तरह, पायथन आपकी जरूरतों का अनुमान
लगाता है

63
टेड: यह एक खराब दिखने वाली हैक के रूप में करने के लिए है '{0}, {0}'.format('test')
उड़ान भेड़

19
मुद्दा यह है: एक नया तर्क जो नए वाक्यविन्यास को आइटम के पुन: व्यवस्थित करने की अनुमति देता है वह एक बिंदु है: आप पुराने वाक्य रचना के साथ भी ऐसा कर सकते हैं। ज्यादातर लोग नहीं जानते हैं कि यह वास्तव में पहले से ही एएनएसआई सी 99 एसटीडी में परिभाषित है! हाल ही की एक कॉपी देखें man sprintfऔर प्लेसहोल्डर्स के $अंदर के अंकन के बारे में जानें%
cfi

29
@ cfi: यदि आप का मतलब कुछ ऐसा है, printf("%2$d", 1, 3)तो "3" प्रिंट करना, यह POSIX में निर्दिष्ट है, C99 नहीं। आपने जिस आदमी पृष्ठ को नोट किया था, "C99 मानक में '$' ... का उपयोग करने वाली शैली शामिल नहीं है।"
थानाटोस

307

कुछ ऐसा जो मोडुलो ऑपरेटर (%) नहीं कर सकता है, उसे:

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

परिणाम

12 22222 45 22222 103 22222 6 22222

बहुत उपयोगी।

एक अन्य बिंदु:, format()एक फ़ंक्शन होने के नाते, अन्य कार्यों में एक तर्क के रूप में इस्तेमाल किया जा सकता है:

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

का परिणाम:

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

17
आप पुरानी शैली के स्वरूपण का उपयोग mapकेवल प्रारूप में आसानी से कर सकते हैं । map('some_format_string_%s'.__mod__, some_iterable)
एजीएफ़

3
@ Cfi: कृपया सिद्ध करें कि आप C99 में ऊपर के उदाहरण को फिर से लिखकर सही हैं
MarcH

9
@ मार्कश: printf("%2$s %1$s\n", "One", "Two");संकलित है gcc -std=c99 test.c -o test, आउटपुट है Two One। लेकिन मैं सही ठहराता हूं: यह वास्तव में एक POSIX एक्सटेंशन है न कि C. मैं इसे फिर से C / C ++ मानक में नहीं पा सकता हूं, जहां मुझे लगा कि मैंने इसे देखा है। कोड 'c90' std फ्लैग के साथ भी काम करता है। sprintfआदमी पेजयह इसे सूचीबद्ध नहीं करता है, लेकिन यह एक सुपरसेट को लागू करने की अनुमति देता है। मेरा मूल तर्क अभी भी मान्य है, CPosix
cfi के

8
यहाँ मेरी पहली टिप्पणी, इस उत्तर पर लागू नहीं होती है। मुझे फंतासी पर पछतावा है। पायथन में हम %प्लेसहोल्डर्स को पुनः व्यवस्थित करने के लिए मॉडुलो ऑपरेटर का उपयोग नहीं कर सकते हैं । मैं अभी भी टिप्पणी स्थिरता के लिए उस पहली टिप्पणी को हटाना नहीं चाहूंगा। मैं यहां अपना गुस्सा निकालने के लिए माफी मांगता हूं। यह अक्सर किए गए कथन के विरुद्ध निर्देशित होता है कि प्रति वाक्य-विन्यास पुराना होने की अनुमति नहीं देगा। एक पूरी तरह से नया सिंटैक्स बनाने के बजाय हम std Posix एक्सटेंशन पेश कर सकते हैं। हम दोनों हो सकते थे।
cfi

17
'modulo' उस ऑपरेटर को संदर्भित करता है जो विभाजन के बाद शेष का मूल्यांकन करता है। इस मामले में प्रतिशत संकेत एक मॉडुलो ऑपरेटर नहीं है।
ऑक्टोपस

148

मान लें कि आप पायथन के loggingमॉड्यूल का उपयोग कर रहे हैं , तो आप स्ट्रिंग प्रारूपण के तर्कों को .debug()स्वयं प्रारूप करने के बजाय विधि के तर्क के रूप में पारित कर सकते हैं :

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

जब तक कि लकड़हारा वास्तव में कुछ नहीं करता है, तब तक प्रारूपण करने से बचा जाता है।


10
यह कुछ उपयोगी जानकारी है जो मैंने अभी सीखी है। यह एक दया की बात है कि यह अपना प्रश्न नहीं है क्योंकि यह मुख्य प्रश्न से अलग लगता है। अफ़सोस ओपी ने अपने प्रश्न को दो अलग-अलग प्रश्नों में विभाजित नहीं किया।
नाग

12
आप इस तरह से तानाशाही प्रारूपण का उपयोग कर सकते हैं: log.debug("some debug info: %(this)s and %(that)s", dict(this='Tom', that='Jerry')) हालांकि, आप .format()यहां नई शैली के सिंटैक्स का उपयोग नहीं कर सकते हैं, यहां तक ​​कि पायथन 3.3 में भी नहीं, जो शर्म की बात है।
Cito


26
इसका प्राथमिक लाभ प्रदर्शन नहीं है (स्ट्रिंग इंटरपोलेशन करना लॉगिंग से आउटपुट के साथ जो कुछ भी कर रहे हैं, उसकी तुलना में त्वरित होगा। उदाहरण के लिए, टर्मिनल में प्रदर्शित करना, डिस्क पर सहेजना) यह है कि यदि आपके पास लॉगिंग एग्रीगेटर है, तो क्या आप बता सकते हैं "आपको इस त्रुटि संदेश के 12 उदाहरण मिले", भले ही वे सभी अलग-अलग 'some_info' मान थे। यदि स्ट्रिंग को log.debug में पास करने से पहले स्ट्रिंग स्वरूपण किया जाता है, तो यह असंभव है। एग्रीगेटर केवल यह कह सकता है "आपके पास 12 अलग लॉग संदेश थे"
जोनाथन हार्टले

7
यदि आप प्रदर्शन के बारे में चिंतित हैं, तो शाब्दिक ताना
बाना

119

Python 3.6 (2016) के रूप में आप चर को बदलने के लिए f- स्ट्रिंग्स का उपयोग कर सकते हैं :

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

f"उपसर्ग पर ध्यान दें । यदि आप पायथन 3.5 या इससे पहले की कोशिश करते हैं, तो आपको ए SyntaxError

Https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings देखें


1
इस सवाल का जवाब नहीं है। एक अन्य उत्तर में प्रदर्शन के बारे में कम से कम बातचीत का उल्लेख किया गया है: stackoverflow.com/a/51167833/7851470
Georgy

60

PEP 3101% पायथन 3 में नए, उन्नत स्ट्रिंग प्रारूपण के साथ ऑपरेटर के प्रतिस्थापन का प्रस्ताव करता है , जहां यह डिफ़ॉल्ट होगा।


14
असत्य: "मौजूदा तंत्र को जगह में छोड़कर पीछे की संगतता को बनाए रखा जा सकता है।" बेशक, स्ट्रिंग स्वरूपण को प्रतिस्थापित.format नहीं करेगा । %
तोबियों

12
नहीं, ब्रेनस्टॉर्म पोस्टुलेशन सही है: "मौजूदा '%' के प्रतिस्थापन के रूप में।" टोबीस उद्धरण का अर्थ है कि दोनों प्रणालियां कुछ समय के लिए साथ-साथ रहेंगी। RTFPEP
phobie

54

लेकिन कृपया जब सब बदलने का प्रयास करने, सावधान रहना अभी मैं एक मुद्दे की खोज की है %के साथ .formatमौजूदा कोड में: '{}'.format(unicode_string)एनकोड unicode_string करने की कोशिश करेंगे और शायद असफल हो जायेगी।

बस इस पायथन इंटरेक्टिव सत्र लॉग को देखें:

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केवल एक स्ट्रिंग है (जिसे Python3 में 'बाइट ऐरे' कहा जाता है) और uएक यूनिकोड स्ट्रिंग (Python3 में 'स्ट्रिंग' कहा जाता है):

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

जब आप एक यूनिकोड ऑब्जेक्ट को %ऑपरेटर के पैरामीटर के रूप में देते हैं तो यह यूनिकोड स्ट्रिंग का उत्पादन करेगा भले ही मूल स्ट्रिंग यूनिकोड नहीं था:

; '{}'.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)

लेकिन .formatसमारोह में "यूनिकोड ईकोडकोड" उठाया जाएगा:

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

और यह केवल यूनिकोड तर्क के साथ काम करेगा यदि मूल स्ट्रिंग यूनिकोड था।

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

या यदि तर्क स्ट्रिंग को स्ट्रिंग में परिवर्तित किया जा सकता है (तथाकथित 'बाइट एरे')


12
जब तक नई formatपद्धति की अतिरिक्त विशेषताओं की वास्तव में जरूरत न हो, तब तक वर्किंग कोड को बदलने का कोई कारण नहीं है ...
तोबियस

आप से पूरी तरह सहमत हूँ, टोबियास, लेकिन कभी-कभी इसकी ज़रूरत होती है जब पाइथन के नए संस्करणों में अपग्रेड किया जाता है
wobmene

2
उदाहरण के लिए? AFAIK, इसकी कभी जरूरत नहीं पड़ी; मैं इस संभावना पर विचार नहीं करता हूं कि %स्ट्रिंग प्रक्षेप कभी भी चले जाएंगे।
तोबियास

4
मैं स्ट्रिंग के लिए% की तुलना में .format () फ़ंक्शन को सुरक्षित मानता हूं। अक्सर मैं शुरुआती लोगों की गलतियों को इस तरह से देखता हूं "p1=%s p2=%d" % "abc", 2या "p1=%s p2=%s" % (tuple_p1_p2,)। आपको लगता है कि यह कोडर की गलती है, लेकिन मुझे लगता है कि यह सिर्फ अजीब दोषपूर्ण सिंटैक्स है जो कि क्विक-स्क्रिप्टी के लिए अच्छा लगता है, लेकिन उत्पादन कोड के लिए बुरा है।
वोबेमेनि

3
लेकिन मुझे .format () का सिंटैक्स पसंद नहीं है, मैं अच्छे पुराने के साथ खुश रहूंगा %s, %02dजैसे "p1=%s p2=%02d".format("abc", 2)। मैं उन लोगों को दोषी मानता हूं जिन्होंने आविष्कार किया और घुंघराले ब्रेसिज़ को मंजूरी दे दी जो आपको उनकी तरह भागने की जरूरत है {{}}और बदसूरत इमो लगती है।
wobmene

35

फिर भी .format(जो मैं जवाबों में नहीं देख रहा हूं) का एक और फायदा : यह ऑब्जेक्ट गुण ले सकता है।

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'

या, एक कीवर्ड तर्क के रूप में:

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

%जहां तक ​​मैं बता सकता हूं , यह संभव नहीं है ।


4
यह समकक्ष की तुलना में आवश्यक से अधिक अपठनीय लगता है 'x is {0}, y is {1}'.format(a.x, a.y)। केवल तब उपयोग किया जाना चाहिए जब a.xऑपरेशन बहुत महंगा हो।
दिनोदोर

13
@dtheodor एक ट्वीक साथ स्थितीय तर्क बजाय ऐसे कीवर्ड तर्क का उपयोग करने के लिए ... 'x is {a.x}, y is {a.y}'.format(a=a)। दोनों उदाहरणों से अधिक पठनीय।
CivFan

1
@CivFan या, यदि आपके पास एक से अधिक वस्तु है,'x is {a.x}, y is {a.y}'.format(**vars())
जैक

1
यह भी एक ही फैशन में इस पर ध्यान दें '{foo[bar]}'.format(foo={'bar': 'baz'}):।
एंटोनी पिंसार्ड

3
यह ग्राहक-सामना करने वाले अनुप्रयोगों के लिए अविश्वसनीय रूप से उपयोगी है, जहां आपका एप्लिकेशन उपयोगकर्ता-आपूर्ति वाले प्रारूप स्ट्रिंग के साथ प्रारूपण विकल्पों का एक मानक सेट प्रदान करता है। यह मेरे लिए हर समय उपयोगी है। उदाहरण के लिए, कॉन्फ़िगरेशन फ़ाइल में कुछ "मैसगैस्ट्रिंग" संपत्ति होगी, जिसे उपयोगकर्ता अपनी 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}इच्छा से या जो चाहें आपूर्ति कर सकता है । पुराने फॉर्मैटर के साथ समान कार्यक्षमता प्रदान करने की कोशिश करने की तुलना में यह बहुत साफ है। यह उपयोगकर्ता द्वारा आपूर्ति की गई प्रारूप स्ट्रिंग्स को अधिक शक्तिशाली बनाता है।
तैवे सिप

35

%formatमेरे टेस्ट से बेहतर प्रदर्शन देता है ।

टेस्ट कोड:

पायथन 2.7.2:

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

परिणाम:

> format: 0.470329046249
> %: 0.357107877731

पायथन 3.5.2

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

परिणाम

> format: 0.5864730989560485
> %: 0.013593495357781649

यह Python2 में दिखता है, अंतर छोटा है जबकि Python3 में, %की तुलना में बहुत तेज है format

नमूना कोड के लिए @Chris Cogdon धन्यवाद।

1 संपादित करें:

जुलाई 2019 में फिर से पायथन 3.7.2 का परीक्षण किया गया।

परिणाम:

> format: 0.86600608
> %: 0.630180146

ज्यादा अंतर नहीं है। मुझे लगता है कि पायथन धीरे-धीरे सुधार कर रहा है।

2 संपादित करें:

किसी ने टिप्पणी में अजगर 3 के एफ-स्ट्रिंग का उल्लेख करने के बाद, मैंने अजगर कोड 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\"}'"))

परिणाम:

format: 0.8331376779999999
%: 0.6314778750000001
f-string: 0.766649943

ऐसा लगता है कि एफ-स्ट्रिंग अभी भी धीमी है %लेकिन इससे बेहतर है format


42
इसके बजाय, str.formatअधिक कार्यक्षमताओं (विशेष रूप से टाइप-विशेष स्वरूपण जैसे '{0:%Y-%m-%d}'.format(datetime.datetime.utcnow())) देता है। प्रदर्शन सभी नौकरियों की पूर्ण आवश्यकता नहीं हो सकती है। इस काम के लिए सही उपकरण का उपयोग करें।
मिन्ह

36
"समयपूर्व अनुकूलन सभी बुराई की जड़ है" या इसलिए डोनाल्ड नथ ने एक बार कहा था ...
यत्रार्थ अग्रवाल

22
एक अच्छी तरह से ज्ञात स्वरूपण योजना के साथ चिपके रहना (जब तक यह आवश्यकताओं के अनुरूप है, जो कि यह अधिकांश मामलों में होता है), और जो दो बार तेज है, कोई "समयपूर्व अनुकूलन" नहीं है, लेकिन बस उचित है। BTW, %ऑपरेटर printfज्ञान का पुन: उपयोग करने की अनुमति देता है ; शब्दकोश प्रक्षेप सिद्धांत का एक बहुत ही सरल विस्तार है।
टोबियास

5
मैंने वास्तव में एक स्थिति में विपरीत का अनुभव किया है। नई शैली का स्वरूपण तेज था। क्या आप उपयोग किए गए परीक्षण कोड प्रदान कर सकते हैं?
डेविड सैंडर्स

8
किसी भी उदाहरण या तर्क के बिना एक गंभीर रूप से बर्बाद पोस्ट की तरह लगता है, बस दावा करता है।
kevr

31

जैसा कि मैंने आज खोजा, स्ट्रिंग्स को फ़ॉर्मेट करने का पुराना तरीका %समर्थन नहीं करता है Decimal, दशमलव निश्चित बिंदु और फ्लोटिंग पॉइंट अंकगणित के लिए पायथन का मॉड्यूल बॉक्स से बाहर है।

उदाहरण (पायथन 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))

आउटपुट:

0.00000000000000000000000312375239000000009907464850 0.000000000000000000000031237523900000000000000000000

निश्चित रूप से काम-आस-पास हो सकते हैं लेकिन आप अभी भी इस format()पद्धति का उपयोग करने पर विचार कर सकते हैं।


1
ऐसा शायद इसलिए है क्योंकि नया-स्टाइल फॉर्मेटिंग str(d)पैरामीटर का विस्तार करने से पहले कॉल करता है, जबकि पुरानी-शैली का फॉर्मेटिंग शायद float(d)पहले कॉल करता है ।
डेविड सैंडर्स

3
आपको ऐसा लगता होगा, लेकिन str(d)रिटर्न "3.12375239e-24", नहीं"0.00000000000000000000000312375239000000000000000000"
जैक

18

यदि आपका अजगर> = 3.6, एफ-स्ट्रिंग स्वरूपित शाब्दिक आपका नया दोस्त है।

यह अधिक सरल, स्वच्छ और बेहतर प्रदर्शन है।

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)

15

एक साइड नोट के रूप में, आपको लॉगिंग के साथ नई शैली स्वरूपण का उपयोग करने के लिए एक प्रदर्शन हिट लेने की आवश्यकता नहीं है। आप के लिए किसी भी वस्तु पारित कर सकते हैं logging.debug, logging.infoआदि है कि लागू __str__जादू विधि। जब लॉगिंग मॉड्यूल ने फैसला किया है कि उसे आपके संदेश ऑब्जेक्ट (जो भी हो) को छोड़ना होगा, str(message_object)ऐसा करने से पहले कॉल करता है। तो आप ऐसा कुछ कर सकते हैं:

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

यह सभी पायथन 3 प्रलेखन ( https://docs.python.org/3/howto/log-cookbook.html#formatting-styles ) में वर्णित है । हालाँकि, यह पायथन 2.6 के साथ भी काम करेगा ( https://docs.python.org/2.6/library/log.html#use-arbitvelop-objects-as-messages )।

इस तकनीक का उपयोग करने के फायदों में से एक, इस तथ्य के अलावा कि यह प्रारूपण-शैली अज्ञेयवादी है, यह है कि यह expensive_funcऊपर दिए गए फ़ंक्शन जैसे आलसी मूल्यों के लिए अनुमति देता है। यह यहाँ पायथन डॉक्स में दी जा रही सलाह का एक और अधिक सुंदर विकल्प प्रदान करता है: https://docs.python.org/2.6/library/log.html#optimization


2
काश मैं इसे और बढ़ा पाता। यह formatप्रदर्शन हिट के बिना लॉगिंग के साथ अनुमति देता है - क्या यह __str__ठीक उसी तरह loggingसे डिज़ाइन किया गया है जिसके लिए डिज़ाइन किया गया है - फ़ंक्शन को कॉल करने के लिए एक एकल अक्षर ( N) को छोटा करता है जो स्ट्रिंग्स को परिभाषित करने के कुछ मानक तरीकों के समान लगता है - और आलसी के लिए अनुमति देता है फ़ंक्शन कॉलिंग। धन्यवाद! +1
CivFan

2
क्या यह logging.Formatter(style='{')पैरामीटर का उपयोग करने के परिणाम में कोई भिन्न है ?
davidA

10

%जब आप regex अभिव्यक्तियों को स्वरूपित कर रहे होते हैं, तो एक स्थिति जहाँ मदद मिल सकती है। उदाहरण के लिए,

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

उठाता है IndexError। इस स्थिति में, आप उपयोग कर सकते हैं:

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

इस के रूप में regex लिखने से बचा जाता है '{type_names} [a-z]{{2}}'। यह तब उपयोगी हो सकता है जब आपके पास दो रेगेक्स होते हैं, जहां एक का उपयोग प्रारूप के बिना अकेले किया जाता है, लेकिन दोनों का संयोजन तैयार किया जाता है।


3
या सिर्फ उपयोग करें '{type_names} [a-z]{{2}}'.format(type_names='triangle|square')। यह कहने की तरह है कि .format()तार का उपयोग करते समय मदद मिल सकती है जिसमें पहले से ही प्रतिशत चरित्र है। ज़रूर। आपको तब उनसे बचना होगा।
अल्फ

1
@Alfe आप सही हैं, और यही कारण है कि उत्तर "One situation where % may help is when you are formatting regex expressions."विशेष रूप से शुरू होता है , मान लें a=r"[a-z]{2}"कि एक regex हिस्सा है जिसे आप दो अलग-अलग अंतिम अभिव्यक्तियों (जैसे c1 = b + aऔर c2 = a) में उपयोग किया जाएगा । मान लें कि एड c1करने की आवश्यकता है format(उदाहरण के bलिए स्वरूपित रनटाइम की आवश्यकता है), लेकिन c2नहीं। तो फिर आप की जरूरत a=r"[a-z]{2}"के लिए c2और a=r"[a-z]{{2}}"के लिए c1.format(...)
जॉर्ज लेइताओ

7

मुझे लगता है कि संस्करण 3.6 के बाद से, हम निम्नलिखित की तरह fstrings का उपयोग कर सकते हैं

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

जो देते हैं

मेरा नाम जॉन स्मिथ है

सब कुछ स्ट्रिंग्स में बदल जाता है

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

परिणाम:

mylist = ['foo', 'bar']

आप फंक्शन पास कर सकते हैं, जैसे अन्य फॉर्मेट विधि में

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

उदाहरण के लिए देते हैं

नमस्कार, यहाँ दिनांक: 16/04/2018 है



2

अजगर 3.6.7 तुलनात्मक:

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

आउटपुट:

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

3
आपको प्रत्येक उदाहरण को कई बार चलाना चाहिए, एक भी रन भ्रामक हो सकता है जैसे ऑपरेटिंग सिस्टम आमतौर पर व्यस्त हो सकता है ताकि आपके कोड के निष्पादन में देरी हो। डॉक्स देखें: docs.python.org/3/library/timeit.html । (अच्छा अवतार,
गायब्रश

1

लेकिन एक बात यह भी है कि अगर आपने घुंघराले ब्रेसेस को नेस्ट किया है, तो फॉर्मेट के लिए काम नहीं करेगा बल्कि काम %करेगा।

उदाहरण:

>>> '{{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}'
>>> 

2
आप ऐसा कर सकते हैं, लेकिन मैं मानता हूं कि यह '{{{0}, {1}}}' है। प्रारूप (1, 2)
सिल्वान ले डेफ

नेस्टेड कीवर्ड कर्ली-ब्रेसेस काम करते हैं और सुंदर हैं।
CivFan
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.