यहां तीन संभावनाएं हैं:
foo = """
this is
a multi-line string.
"""
def f1(foo=foo): return iter(foo.splitlines())
def f2(foo=foo):
retval = ''
for char in foo:
retval += char if not char == '\n' else ''
if char == '\n':
yield retval
retval = ''
if retval:
yield retval
def f3(foo=foo):
prevnl = -1
while True:
nextnl = foo.find('\n', prevnl + 1)
if nextnl < 0: break
yield foo[prevnl + 1:nextnl]
prevnl = nextnl
if __name__ == '__main__':
for f in f1, f2, f3:
print list(f())
इसे चलाना मुख्य स्क्रिप्ट के रूप में पुष्टि करता है कि तीन कार्य बराबर हैं। साथ timeit
(और एक * 100
के लिए foo
और अधिक सटीक माप के लिए पर्याप्त तार पाने के लिए):
$ python -mtimeit -s'import asp' 'list(asp.f3())'
1000 loops, best of 3: 370 usec per loop
$ python -mtimeit -s'import asp' 'list(asp.f2())'
1000 loops, best of 3: 1.36 msec per loop
$ python -mtimeit -s'import asp' 'list(asp.f1())'
10000 loops, best of 3: 61.5 usec per loop
ध्यान दें कि हमें list()
यह सुनिश्चित करने के लिए कॉल की आवश्यकता है कि ट्रैवर्स को ट्रैवर्स किया गया है, न कि केवल निर्मित।
IOW, भोली कार्यान्वयन बहुत तेज़ है यह मज़ेदार भी नहीं है: find
कॉल के साथ मेरे प्रयास की तुलना में 6 गुना तेज है , जो बदले में निचले स्तर के दृष्टिकोण से 4 गुना तेज है।
बनाए रखने के लिए सबक: माप हमेशा एक अच्छी चीज है (लेकिन सटीक होना चाहिए); स्ट्रिंग तरीकों पसंद splitlines
बहुत तेजी से तरीकों से लागू कर रहे हैं; बहुत कम स्तर पर प्रोग्रामिंग द्वारा तार एक साथ रखना (लूप ऑफ द लूप्स)+=
बहुत छोटे टुकड़ों के ) काफी धीमा हो सकता है।
संपादित करें : @ याकूब का प्रस्ताव, दूसरों के रूप में एक ही परिणाम देने के लिए थोड़ा संशोधित (रेखा पर रिक्त स्थान रखा जाता है), यानी:
from cStringIO import StringIO
def f4(foo=foo):
stri = StringIO(foo)
while True:
nl = stri.readline()
if nl != '':
yield nl.strip('\n')
else:
raise StopIteration
मापने देता है:
$ python -mtimeit -s'import asp' 'list(asp.f4())'
1000 loops, best of 3: 406 usec per loop
.find
आधारित दृष्टिकोण के रूप में बहुत अच्छा नहीं है - फिर भी, ध्यान में रखने योग्य है क्योंकि यह छोटे ऑफ-बाय-वन बग (किसी भी लूप जहां आपको +1 और -1 की घटनाएँ दिखाई देती हैं, जैसे कि मेरे f3
ऊपर, कम हो सकता है) एक-एक संदेह को ट्रिगर करें - और इसलिए कई लूप्स होने चाहिए जिनमें इस तरह की ट्वीक्स की कमी हो और उन्हें होना चाहिए - हालांकि मेरा मानना है कि मेरा कोड भी सही है क्योंकि मैं अन्य कार्यों के साथ इसके आउटपुट की जांच करने में सक्षम था)।
लेकिन विभाजित-आधारित दृष्टिकोण अभी भी नियम है।
एक तरफ: संभवतः के लिए बेहतर शैली f4
होगी:
from cStringIO import StringIO
def f4(foo=foo):
stri = StringIO(foo)
while True:
nl = stri.readline()
if nl == '': break
yield nl.strip('\n')
कम से कम, यह थोड़ा कम क्रिया है। अनुगामी स्ट्रिपिंग की आवश्यकता \n
दुर्भाग्य से और while
पाश के तेजी से प्रतिस्थापन को रोकती है return iter(stri)
(जिस iter
भाग पायथन के आधुनिक संस्करणों में बेमानी है, मेरा मानना है कि 2.3 या 2.4 के बाद से, लेकिन यह भी सहज है)। शायद कोशिश करने लायक भी:
return itertools.imap(lambda s: s.strip('\n'), stri)
या इसके रूपांतर - लेकिन मैं यहाँ रोक रहा हूँ क्योंकि यह एक बहुत ही सैद्धांतिक अभ्यास है जो strip
सबसे सरल और सबसे तेज़ आधारित है।
foo.splitlines()
सही पर पुनरावृति कर सकते हैं ?