স্ট্রিং ফর্ম্যাটিং:% বনাম। ফর্ম্যাট


1348

পাইথন ২.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
রেফারেন্সের জন্য: নতুন format()ফর্ম্যাটিং শৈলীর জন্য পুরানো- %ভিত্তিক বিন্যাস শৈলীর জন্য পাইথন 3 ডকুমেন্টেশন ।
লুটজ প্রিচেল্ট


1
আপনার দ্বিতীয় প্রশ্নের উত্তর দেওয়ার জন্য, ৩.২ থেকে আপনি custom} ফর্ম্যাটটি ব্যবহার করতে পারেন যদি আপনি একটি কাস্টম ফর্ম্যাটার ব্যবহার করেন ( docs.python.org/3/library/logging.html#logging. Formatter )
yjost

উত্তর:


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'}
টেড

128
নোট করুন যে আপনি সময় নষ্ট করবেন log.debug("something: %s" % x)তবে এর জন্য নয় log.debug("something: %s", x) স্ট্রিং ফর্ম্যাটিং পদ্ধতিতে পরিচালনা করা হবে এবং এটি লগ করা না হলে আপনি পারফরম্যান্স হিট পাবেন না। সর্বদা হিসাবে, পাইথন আপনার প্রয়োজনগুলি পূর্বাভাস দেয় =)
ডার্কলাইন

63
টেড: যে একই কাজ করতে একটি খারাপ সুদর্শন হ্যাক এর '{0}, {0}'.format('test')
উড়ন্ত ভেড়া

19
মুল বক্তব্যটি: নতুন সিনট্যাক্সটি আইটেমগুলির পুনঃক্রম করতে দেয় এমন এক পুনরাবৃত্ত যুক্তি হ'ল একটি বিন্দু: পুরানো বাক্য গঠনটি দিয়ে আপনি একই কাজ করতে পারেন। বেশিরভাগ লোক জানে না যে এটি ইতিমধ্যে আনসি সি 99 স্ট্যান্ডে সংজ্ঞায়িত হয়েছে! একটি সাম্প্রতিক অনুলিপি দেখুন man sprintfএবং স্থানধারকগুলির মধ্যে $স্বরলিপি সম্পর্কে শিখুন%
সিএফআই

29
@ সিফি: আপনি যদি printf("%2$d", 1, 3)"3" মুদ্রণ করার মতো কিছু বোঝেন তবে এটি পসিক্সে নির্দিষ্ট করা হয়েছে, সি 99 নয়। আপনি যে ম্যান পেজটি নোট করেছেন তা উল্লেখ করেছেন, "সি 99 স্ট্যান্ডার্ডটিতে '$'…" ব্যবহার করে স্টাইলটি অন্তর্ভুক্ত করা হয় না।
থানাটোস

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

3
@ সিফি: অনুগ্রহ করে উপরের উদাহরণটি C99
মার্চএইচ

9
@ মার্সএইচএইচ: printf("%2$s %1$s\n", "One", "Two");সংকলিত gcc -std=c99 test.c -o test, আউটপুটটি Two One। তবে আমি সংশোধন করে দাঁড়িয়েছি: এটি আসলে একটি পসিক্স এক্সটেনশন এবং সি নয় I আমি এটি আবার সি / সি ++ স্ট্যান্ডার্ডে খুঁজে পাই না, যেখানে আমি ভেবেছিলাম যে আমি এটি দেখেছি। কোডটি 'c90' স্ট্যান্ড ফ্ল্যাগের সাথেও কাজ করে। sprintfman পৃষ্ঠাএটি এটি তালিকাভুক্ত করে না, তবে একটি সুপারসেট বাস্তবায়নের জন্য লিবকে অনুমতি দেয়। আমার মূল যুক্তি, এখনও বৈধ প্রতিস্থাপন Cসঙ্গেPosix
cfi

8
আমার এখানে প্রথম মন্তব্য, এই উত্তরের প্রয়োগ হয় না। আমি শব্দবন্ধ অনুশোচনা। পাইথনে আমরা %স্থানধারীদের পুনরায় অর্ডার করার জন্য মডুলো অপারেটরটি ব্যবহার করতে পারি না । আমি এখনও মন্তব্যের ধারাবাহিকতার জন্য সেই প্রথম মন্তব্যটি মুছে ফেলতে চাই না। আমি এখানে আমার রাগ ছড়িয়ে দেওয়ার জন্য ক্ষমা চাইছি। এটি প্রায়শই করা বিবৃতিটির বিরুদ্ধে নির্দেশিত হয় যে প্রতি সেচ পুরানো বাক্য গঠন এটিকে অনুমতি দেয় না। সম্পূর্ণ নতুন সিনট্যাক্স তৈরির পরিবর্তে আমরা স্ট্যান্ড পসিক্স এক্সটেনশনগুলি চালু করতে পারতাম। আমরা উভয় থাকতে পারে।
সিএফআই

17
'মডুলো' অপারেটরকে বোঝায় যা বিভাগের পরে একটি অবশিষ্ট অংশকে মূল্যায়ন করে। এই ক্ষেত্রে শতকরা চিহ্নটি কোনও মডুলো অপারেটর নয়।
অক্টোপাস

148

ধরে নেওয়া যাক আপনি পাইথনের loggingমডিউল ব্যবহার করছেন , আপনি .debug()নিজেই ফরম্যাটিংটি না করে স্ট্রিং ফর্ম্যাটিং আর্গুমেন্টগুলিকে মেথডে আর্গুমেন্ট হিসাবে পাস করতে পারেন :

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

লগার আসলে কিছু লগ না করা হলে এটি ফর্ম্যাট করা এড়িয়ে যায়।


10
এটি এমন কিছু দরকারী তথ্য যা আমি এখনই শিখেছি। এটি দুঃখের বিষয় এটির নিজস্ব প্রশ্ন নেই কারণ এটি প্রধান প্রশ্নের সাথে পৃথক বলে মনে হচ্ছে। ওপেনার করুণা তার প্রশ্ন দুটি পৃথক প্রশ্নে বিভক্ত করেনি।
snth

12
আপনি ডিক বিন্যাসটি এর মতো ব্যবহার করতে পারেন: log.debug("some debug info: %(this)s and %(that)s", dict(this='Tom', that='Jerry')) তবে, আপনি .format()এখানে নতুন স্টাইলের সিনট্যাক্সটি ব্যবহার করতে পারবেন না , পাইথন ৩.৩ এও নয়, এটি লজ্জাজনক।
সিটো

15
@ সিটো: এটি দেখুন: plumberjack.blogspot.co.uk/2010/10/…
বিনয় সাজিপ

26
এর প্রাথমিক সুবিধাটি পারফরম্যান্স নয় (লগিং থেকে আউটপুট নিয়ে যা যা করছেন তার সাথে তুলনামূলক স্ট্রিং ইন্টারপোলেশন করা দ্রুত হবে, যেমন টার্মিনালে প্রদর্শিত, ডিস্কে সংরক্ষণ করা) এটি যদি আপনার লগিং এগ্রিগেটর থাকে তবে এটি আপনাকে বলতে পারে "আপনি এই ত্রুটি বার্তার 12 টি উদাহরণ পেয়েছেন", এমনকি যদি তাদের সকলেরই কিছু 'কিছু_ ইনফো' মান থাকে। যদি স্ট্রিং বিন্যাসটি log.debug এ স্ট্রিংটি পাস করার আগে করা হয়, তবে এটি অসম্ভব। সমবেতকারী কেবল "আপনার কাছে 12 টি পৃথক লগ বার্তা ছিল" বলতে পারবেন
জোনাথন হার্টলি

7
আপনি যদি পারফরম্যান্স সম্পর্কে উদ্বিগ্ন হন তবে ডিক () শ্রেণি ইনস্ট্যান্টেশনের পরিবর্তে আক্ষরিক ডিক}} সিনট্যাক্সটি ব্যবহার করুন: ডগহেলম্যান ডটকম
২০১২ /

119

পাইথন ৩.6 (২০১ 2016) অনুযায়ী আপনি ভেরিয়েবলগুলি বিকল্প হিসাবে এফ স্ট্রিং ব্যবহার করতে পারেন :

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

f"উপসর্গটি নোট করুন । যদি আপনি পাইথন 3.5 বা তার আগে এর চেষ্টা করে থাকেন তবে আপনি একটি পাবেন SyntaxError

Https://docs.python.org/3.6/references/lexical_analysis.html#f-strings দেখুন


1
এটি প্রশ্নের উত্তর দেয় না। আর একটি উত্তর যা এফ-স্ট্রিংয়ের উল্লেখ করেছে কমপক্ষে পারফরম্যান্সের বিষয়ে আলোচনা: stackoverflow.com/a/51167833/7851470
জর্জি

60

পিইপি 3101% পাইথন 3 এ নতুন, উন্নত স্ট্রিং ফর্ম্যাটিংয়ের সাথে অপারেটরের প্রতিস্থাপনের প্রস্তাব দেয় , যেখানে এটি ডিফল্ট হবে।


14
অস্পষ্ট: "বিদ্যমান ব্যবস্থাগুলি স্থানে রেখে পিছনে সামঞ্জস্যতা বজায় রাখা যায়"; অবশ্যই, স্ট্রিং বিন্যাস প্রতিস্থাপন.format করবে না । %
টোবিয়াস

12
না, ব্রেইনস্টোরমস পোস্টুলেশন সত্য: "বিদ্যমান '%' এর প্রতিস্থাপন হিসাবে লক্ষ্য করা গেছে"। টোবিয়াসের উদ্ধৃতি অর্থ উভয় ব্যবস্থা কিছু সময়ের জন্য সহাবস্থান করবে। আরটিএফপেইপ
ফোবি

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কেবল একটি স্ট্রিং (পাইথন 3 এ 'বাইট অ্যারে' নামে পরিচিত) এবং uএটি একটি ইউনিকোড স্ট্রিং (পাইথন 3-তে 'স্ট্রিং' নামে পরিচিত):

; '%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
এই ক্ষেত্রে? আফাইক, এটি কখনও প্রয়োজন হয় নি ; আমি সম্ভবত এটি বিবেচনা করি না যে %স্ট্রিং ইন্টারপোলেশনটি কখনও চলে যাবে।
টোবিয়াস

4
আমি। Formt () ফাংশনটিকে স্ট্রিংয়ের জন্য% এর চেয়ে বেশি নিরাপদ মনে করি। প্রায়শই আমি এইভাবে "p1=%s p2=%d" % "abc", 2বা প্রাথমিকভাবে ভুল দেখতে পাই "p1=%s p2=%s" % (tuple_p1_p2,)। আপনি এটি কোডারের দোষ মনে করতে পারেন তবে আমি মনে করি এটি কেবল অদ্ভুত ত্রুটিযুক্ত বাক্য গঠন যা দ্রুত-স্ক্রিপ্টির জন্য দেখতে দুর্দান্ত তবে প্রোডাকশন কোডের পক্ষে খারাপ।
wobmene

3
কিন্তু আমি .format () বাক্য গঠন প্রণালী মত না, আমি ভাল পুরানো সঙ্গে সুখী হতে চাই %s, %02dমত "p1=%s p2=%02d".format("abc", 2)। যারা কুঁকড়ানো ধনুর্বন্ধনী বিন্যাস আবিষ্কার করেছেন এবং অনুমোদন করেছেন তাদেরকে আমি দোষ দিচ্ছি যেগুলি আপনাকে এড়ানো পছন্দ করে {{}}এবং কুৎসিত ইমো দেখায় needs
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অপারেশনটি খুব ব্যয়বহুল হলে কেবল ব্যবহার করা উচিত ।
dtheodor

13
@dtheodor একটি খামচি দিয়ে অবস্থানগত যুক্তি পরিবর্তে একটি শব্দ যুক্তি ব্যবহার করতে ... 'x is {a.x}, y is {a.y}'.format(a=a)। উভয় উদাহরণের চেয়ে বেশি পঠনযোগ্য।
সিভিফ্যান

1
@ সিভিফ্যান বা আপনার যদি একাধিক অবজেক্ট থাকে'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আমার পরীক্ষা থেকে ভাল পারফরম্যান্স দেয় ।

পরীক্ষার কোড:

পাইথন ২.7.২:

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

পাইথন ৩.৩.২

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

নমুনা কোডের জন্য @ ক্রিস কগডনকে ধন্যবাদ।

সম্পাদনা 1:

জুলাই 2019 সালে পাইথনে 3.7.2 এ আবার পরীক্ষা করা হয়েছে।

ফলাফল:

> format: 0.86600608
> %: 0.630180146

খুব বেশি পার্থক্য নেই। আমার ধারণা পাইথন ধীরে ধীরে উন্নতি করছে।

সম্পাদনা 2:

কেউ মন্তব্যে পাইথন 3 এর এফ স্ট্রিং উল্লেখ করার পরে, আমি পাইথন ৩..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
একটি সুপরিচিত ফর্ম্যাটিং স্কিমের সাথে আটকে থাকা (যতক্ষণ না এটি প্রয়োজনের সাথে সার্থক হয়, এটি এটি বেশিরভাগ ক্ষেত্রেই করে) এবং যা দ্বিগুণ দ্রুত, এটি কোনও "অকাল অপ্টিমাইজেশন" নয় তবে কেবল যুক্তিসঙ্গত। বিটিডাব্লু, %অপারেটর printfজ্ঞান পুনরায় ব্যবহার করতে দেয় ; অভিধানের অন্তরঙ্গকরণ নীতিটির একটি খুব সাধারণ বর্ধন।
টোবিয়াস

5
আমি আসলে এক পরিস্থিতিতে বিপরীত অভিজ্ঞতা পেয়েছি। নতুন স্টাইলের ফর্ম্যাটিংটি দ্রুত ছিল। আপনি যে পরীক্ষার কোডটি ব্যবহার করেছিলেন তা কি সরবরাহ করতে পারবেন?
ডেভিড স্যান্ডার্স

8
কোনও দাবি বা যুক্তি ছাড়াই গুরুতরভাবে নষ্ট পোস্টের মতো মনে হচ্ছে, কেবল দাবি।
কেভর

31

যেমনটি আমি আজ আবিষ্কার করেছি, স্ট্রিংগুলিকে ফর্ম্যাট করার পুরানো উপায়টি %সমর্থন করে না Decimal, পাইথনের মডিউল দশমিক স্থির পয়েন্ট এবং ভাসমান পয়েন্ট গণিত, বাক্সের বাইরে।

উদাহরণ (পাইথন ৩.৩.৫ ব্যবহার করে):

#!/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.000000000000000000000003123752390000009907464850 0.0000000000000000000003123752390000000000000000

অবশ্যই কাজের আশেপাশে থাকতে পারে তবে আপনি এখনই এই 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/logging-cookbook.html# formtting-styles )। যাইহোক, এটি পাইথন ২.6 এর সাথেও কাজ করবে ( https://docs.python.org/2.6/library/logging.html#used-arbitrary-objects-as- ম্যাসেজগুলি )।

এই কৌশলটি ব্যবহার করার একটি সুবিধা, এটির বিন্যাসকরণ-শৈলীর অজ্ঞেয়বাদী ব্যতীত, এটি অলস মানের জন্য যেমন expensive_funcউপরের ফাংশনটিকে অনুমতি দেয় । পাইথন ডক্সে এখানে দেওয়া পরামর্শের জন্য এটি আরও মার্জিত বিকল্প সরবরাহ করে: https://docs.python.org/2.6/library/logging.html#optimization


2
আমি আশা করি আমি এই আরও upvote করতে পারে। এটি formatপারফরম্যান্স হিট ছাড়াই লগিং করতে দেয় - এটির জন্য __str__যেমন loggingনকশা করা হয়েছিল ঠিক তেমনভাবে ওভাররাইড করে - ফাংশন কলটিকে একটি একক চিঠিতে সংক্ষিপ্ত করে ( N) যা স্ট্রিংগুলি সংজ্ঞায়িত করার কিছু মানক উপায়ের সাথে খুব মিল মনে করে - এবং অলসতার জন্য অনুমতি দেয় ফাংশন কলিং। ধন্যবাদ! +1
সিভিফ্যান

2
logging.Formatter(style='{')প্যারামিটারটি ব্যবহার করার ক্ষেত্রে এটি কি অন্যরকম ?
ডেভিডা

10

%আপনি যখন রেজেক্স এক্সপ্রেশনগুলিকে ফর্ম্যাট করছেন তখন এমন একটি পরিস্থিতি হ'ল সহায়তা করতে পারে। উদাহরণ স্বরূপ,

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

উত্থাপন IndexError। এই পরিস্থিতিতে, আপনি ব্যবহার করতে পারেন:

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

এটি হিসাবে রেজেক্স হিসাবে লেখা এড়ানো '{type_names} [a-z]{{2}}'। এটি আপনার পক্ষে দুটি রেইজেক্স থাকতে পারে, যেখানে বিন্যাস ছাড়াই একা ব্যবহৃত হয়, তবে উভয়ের সংমিশ্রণটি বিন্যাস করা হয় ted


3
বা শুধু ব্যবহার '{type_names} [a-z]{{2}}'.format(type_names='triangle|square')। এটি .format()ইতিমধ্যে শতকরা অক্ষরযুক্ত স্ট্রিংগুলি ব্যবহার করার সময় সাহায্য করতে পারে বলে মত । অবশ্যই। আপনাকে তখন পালাতে হবে।
Alfe

1
@ অ্যালফ আপনি ঠিকই বলেছেন, আর এ কারণেই উত্তরটি "One situation where % may help is when you are formatting regex expressions."বিশেষত শুরু হয় , ধরে a=r"[a-z]{2}"নেওয়া একটি রেইজেক্স অংশ যা আপনাকে দুটি পৃথক চূড়ান্ত প্রকাশে ব্যবহার করা হবে (যেমন c1 = b + aএবং c2 = a)। অনুমান c1চাহিদা করা formated (যেমন bরানটাইম ফরম্যাট করা প্রয়োজন), কিন্তু c2না। তারপর আপনার যা দরকার a=r"[a-z]{2}"জন্য c2এবং a=r"[a-z]{{2}}"জন্য c1.format(...)
জর্জি লিটাও

7

আমি যোগ করব যেহেতু সংস্করণ 3.6, আমরা নিম্নলিখিতের মতো স্ট্রাস্টিং ব্যবহার করতে পারি

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

যা দেয়

আমার নাম জন স্মিথ

সবকিছু স্ট্রিংয়ে রূপান্তরিত হয়

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

ফলাফল:

মাইলিস্ট = ['foo', 'বার']

অন্যদের বিন্যাস পদ্ধতিতে আপনিও ফাংশনটি পাস করতে পারেন

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

উদাহরণস্বরূপ প্রদান

হ্যালো, এখানে তারিখটি রয়েছে: 16/04/2018



2

পাইথন ৩.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)
সিলেয়ান এলইইউএনএফএফ

নেস্টেড কীওয়ার্ড কোঁকড়ানো-ধনুর্বন্ধনী কাজ করে এবং দুর্দান্ত।
সিভিফ্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.