দুটি স্ট্রিং সংহত করতে '+' ব্যবহার না করার কোনও কারণ?


123

পাইথনের একটি সাধারণ অ্যান্টিপ্যাটার্ন হ'ল +লুপের সাহায্যে স্ট্রিংগুলির ক্রম সংযুক্ত করা । এটি খারাপ কারণ পাইথন ইন্টারপ্রেটারকে প্রতিটি পুনরাবৃত্তির জন্য একটি নতুন স্ট্রিং অবজেক্ট তৈরি করতে হবে এবং এটি চতুর্ভুজ সময় নিয়ে শেষ হবে। (সিপথনের সাম্প্রতিক সংস্করণগুলি কিছু ক্ষেত্রে আপাতদৃষ্টিতে এটি অনুকূল করে তুলতে পারে, তবে অন্যান্য বাস্তবায়ন করতে পারে না, সুতরাং প্রোগ্রামাররা এটির উপর নির্ভর করা থেকে নিরুৎসাহিত হন)) ''.joinএটি করার সঠিক উপায়।

যাইহোক, আমি এটি শুনেছি ( স্ট্যাক ওভারফ্লোতে এখানে অন্তর্ভুক্ত ) আপনার কখনও কখনও+ স্ট্রিং কনটেনটেশনের জন্য ব্যবহার করা উচিত নয়, পরিবর্তে সর্বদা ব্যবহার করা ''.joinবা বিন্যাসের স্ট্রিং ব্যবহার করা উচিত । আমি যদি বুঝতে পারি না যে আপনি কেবল দুটি স্ট্রিংকেই কাটাচ্ছেন তবে কেন এটি হচ্ছে। যদি আমার বোধগম্যতা সঠিক হয় তবে এটি চতুর্ভুজ সময় নিতে হবে না এবং আমি মনে করিa + b যে ক্লিনার এবং আরও বেশি ''.join((a, b))বা পড়ার চেয়ে বেশি হয় বা হয় না '%s%s' % (a, b)

+দুটি স্ট্রিং সংমিশ্রনের জন্য ব্যবহার করা কি ভাল অনুশীলন ? বা এমন কোন সমস্যা আছে যা সম্পর্কে আমি অবগত নই?


এটি আরও সুস্পষ্ট এবং আপনার আরও বেশি নিয়ন্ত্রণ রাখতে হবে না তবে এর সামান্য ধীর, স্ট্রিং বাশিং বাণিজ্য বন্ধ করুন: পি
জাকব বোয়ার

আপনি কি বলছেন +দ্রুত বা ধীর? এবং কেন?
তাইমন

1
+ দ্রুততর, In [2]: %timeit "a"*80 + "b"*80 1000000 loops, best of 3: 356 ns per loop In [3]: %timeit "%s%s" % ("a"*80, "b"*80) 1000000 loops, best of 3: 907 ns per loop
জাকব বোয়ার 13

4
In [3]: %timeit "%s%s" % (a, b) 1000000 loops, best of 3: 590 ns per loop In [4]: %timeit a + b 10000000 loops, best of 3: 147 ns per loop
জাকব বোয়ার

1
@ জ্যাকববায়ার এবং অন্যান্যরা: "স্ট্রিং কনটেনটেশন খারাপ" যুক্তিটির গতির সাথে প্রায় কিছুই করার নেই, তবে এর সাথে স্বয়ংক্রিয় ধরণের রূপান্তরটির সুবিধা নিয়ে __str__। উদাহরণস্বরূপ আমার উত্তর দেখুন।
ইজকাটা

উত্তর:


119

দুটি স্ট্রিং দিয়ে কনটেন্টেট করার ক্ষেত্রে কোনও ভুল নেই +। আসলে এটি পড়ার চেয়ে সহজ ''.join([a, b])

আপনি ঠিক বলেছেন যদিও 2 টিরও বেশি স্ট্রিং দিয়ে কন্টেন্টেট করা +হচ্ছে একটি O (n ^ 2) অপারেশন (ও (এন) এর সাথে তুলনা করা join) এবং সুতরাং এটি অকার্যকর হয়ে যায়। তবে এটি একটি লুপ ব্যবহার করে না। এমনকি a + b + c + ...ও (এন ^ 2), কারণ প্রতিটি যুক্তি একটি নতুন স্ট্রিং উত্পাদন করে।

সিপিথন ২.৪ এবং তারপরে এটি হ্রাস করার চেষ্টা করুন, তবে join২ টিরও বেশি স্ট্রিং সংশ্লেষ করার সময় এটি ব্যবহার করার পরামর্শ দেওয়া হচ্ছে ।


5
@ মিউট্যান্ট: .joinএকটি পুনরাবৃত্তিযোগ্য লাগে, তাই উভয়ই .join([a,b])এবং .join((a,b))বৈধ।
প্রতিষ্ঠিত

1
জবর সময় ব্যবহার এ প্রজ্ঞান +বা +=(2013 থেকে) এ গৃহীত উত্তরে stackoverflow.com/a/12171382/378826 (Lennart Regebro থেকে) CPython এমনকি 2.3+ এবং শুধুমাত্র বেছে "পরিশেষে যোগ / যোগদানের" প্যাটার্ন যদি এই পরিষ্কার অনাবৃত হাতে সমস্যা সমাধানের জন্য ধারণা।
বিস্ময়কর

49

দুটি পাইথন স্ট্রিং সংযুক্ত করার জন্য প্লাস অপারেটর পুরোপুরি সূক্ষ্ম সমাধান । তবে আপনি যদি আরও দুটি স্ট্রিং যুক্ত করেন (n> 25), আপনি অন্য কিছু ভাবতে চাইতে পারেন।

''.join([a, b, c]) কৌশল একটি কর্মক্ষমতা অপ্টিমাইজেশন।


2
একটি টিপল কি তালিকার চেয়ে ভাল হবে না?
চোরমাস্টার

7
টিপল দ্রুততর হবে - কোডটি কেবল একটি উদাহরণ ছিল :) সাধারণত দীর্ঘ একাধিক স্ট্রিং ইনপুট গতিশীল থাকে।
মিক্কো ওহতামা

5
@ মার্টিনেউ আমি মনে করি তার অর্থ append()একটি তালিকাতে গতিশীলভাবে উত্পাদন এবং স্ট্রিং তৈরি করা।
পিটার সি

5
এখানে বলা দরকার: টিপল সাধারণত স্লোয়ার কাঠামো হয়, বিশেষত যদি এটি বাড়ছে। তালিকার সাহায্যে আপনি list.extend (list_of_items) এবং list.append (আইটেম) ব্যবহার করতে পারেন যা গতিশীল স্টাফগুলিকে সংযুক্ত করার সময় অনেক দ্রুত হয়।
অ্যান্টি হাপালা

6
+1 এর জন্য n > 25। মানুষের কোথাও শুরু করার জন্য রেফারেন্স পয়েন্ট দরকার।
n611x007

8

এই ধারণাটি যে কখনও কখনও স্ট্রিং কনটেনটেশনের জন্য + ব্যবহার করা উচিত নয়, তবে এর পরিবর্তে সর্বদা '' .জাইন ব্যবহার করা উচিত একটি কল্পকাহিনী। এটি সত্য যে +অপরিবর্তনীয় স্ট্রিং অবজেক্টের অপ্রয়োজনীয় অস্থায়ী অনুলিপি তৈরি করে তবে অন্যটি অবহিত সত্য নয় যে joinএকটি লুপে কল করা সাধারণত ওভারহেড যুক্ত করে function call। আপনার উদাহরণ নিতে দিন।

দুটি তালিকা তৈরি করুন, একটি লিঙ্কযুক্ত এসও প্রশ্ন থেকে এবং অন্যটি আরও বড় বানোয়াট

>>> myl1 = ['A','B','C','D','E','F']
>>> myl2=[chr(random.randint(65,90)) for i in range(0,10000)]

দুটি ফাংশন তৈরি করেন, দেয় UseJoinএবং UsePlusনিজ নিজ ব্যবহার করতে joinএবং +কার্যকারিতা।

>>> def UsePlus():
    return [myl[i] + myl[i + 1] for i in range(0,len(myl), 2)]

>>> def UseJoin():
    [''.join((myl[i],myl[i + 1])) for i in range(0,len(myl), 2)]

প্রথম তালিকার সাথে টাইমিট চালাতে দেয়

>>> myl=myl1
>>> t1=timeit.Timer("UsePlus()","from __main__ import UsePlus")
>>> t2=timeit.Timer("UseJoin()","from __main__ import UseJoin")
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
2.48 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
2.61 usec/pass
>>> 

তাদের প্রায় একই রানটাইম আছে।

সিপ্রোফাইল ব্যবহার করতে দেয়

>>> myl=myl2
>>> cProfile.run("UsePlus()")
         5 function calls in 0.001 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001    0.001    0.001 <pyshell#1376>:1(UsePlus)
        1    0.000    0.000    0.001    0.001 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {range}


>>> cProfile.run("UseJoin()")
         5005 function calls in 0.029 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.015    0.015    0.029    0.029 <pyshell#1388>:1(UseJoin)
        1    0.000    0.000    0.029    0.029 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     5000    0.014    0.000    0.014    0.000 {method 'join' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {range}

এবং দেখে মনে হচ্ছে যে জয়েন ব্যবহার করে অপ্রয়োজনীয় ফাংশন কলগুলি ফলাফল করে যা ওভারহেড যুক্ত করতে পারে।

এখন আবার প্রশ্নে ফিরে আসছি। একজনের কি সব ক্ষেত্রে +ওভার ব্যবহারকে নিরুৎসাহিত করা উচিত join?

আমি বিশ্বাস করি না, বিষয়গুলি বিবেচনায় নেওয়া উচিত

  1. প্রশ্নে স্ট্রিংয়ের দৈর্ঘ্য
  2. কনকাটেনেশন অপারেশন এর।

এবং অফ-কোর্সে উন্নয়নের প্রাক-পরিপক্ক অপটিমাইজেশনটি মন্দ।


7
অবশ্যই, ধারণাটি joinলুপের ভিতরেই ব্যবহার না করা হবে - বরং লুপটি এমন একটি অনুক্রম তৈরি করবে যা যোগ দেওয়ার জন্য পাস হবে be
jsbueno

7

একাধিক ব্যক্তির সাথে কাজ করার সময়, কখনও কখনও ঠিক কী ঘটছে তা জানা খুব কঠিন। কনটেনটেশনের পরিবর্তে ফর্ম্যাট স্ট্রিং ব্যবহার করা একটি বিশেষ বিরক্তি এড়াতে পারে যা আমাদের কাছে পুরো এক টন হয়েছিল:

বলুন, একটি ফাংশনটির জন্য একটি আর্গুমেন্ট প্রয়োজন এবং আপনি স্ট্রিংয়ের প্রত্যাশায় এটি লিখেন:

In [1]: def foo(zeta):
   ...:     print 'bar: ' + zeta

In [2]: foo('bang')
bar: bang

সুতরাং, এই ক্রিয়াকলাপটি পুরো কোড জুড়ে প্রায়শই ব্যবহার করা যেতে পারে। আপনার সহকর্মীরা এটি ঠিক কী করতে পারে তা জানতে পারে তবে প্রয়োজনীয়ভাবে অভ্যন্তরগুলিতে পুরোপুরি আপ-টু স্পিড হওয়া উচিত নয় এবং জানেন না যে ফাংশনটি কোনও স্ট্রিংয়ের প্রত্যাশা করে। এবং তাই তারা এই সাথে শেষ হতে পারে:

In [3]: foo(23)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

/home/izkata/<ipython console> in foo(zeta)

TypeError: cannot concatenate 'str' and 'int' objects

আপনি কেবল একটি ফর্ম্যাট স্ট্রিং ব্যবহার করলে কোনও সমস্যা হবে না:

In [1]: def foo(zeta):
   ...:     print 'bar: %s' % zeta
   ...:     
   ...:     

In [2]: foo('bang')
bar: bang

In [3]: foo(23)
bar: 23

সংজ্ঞায়িত সমস্ত ধরণের অবজেক্টের ক্ষেত্রেও এটি একই __str__, যা পাসও হতে পারে:

In [1]: from datetime import date

In [2]: zeta = date(2012, 4, 15)

In [3]: print 'bar: ' + zeta
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

TypeError: cannot concatenate 'str' and 'datetime.date' objects

In [4]: print 'bar: %s' % zeta
bar: 2012-04-15

সুতরাং হ্যাঁ: আপনি যদি কোনও ফর্ম্যাট স্ট্রিং ব্যবহার করতে পারেন তবে এটি করুন এবং পাইথনের যা আছে তার সুবিধা নিন।


1
সুস্পষ্ট যুক্তিযুক্ত মতামতের জন্য +1। আমি এখনও আমার পক্ষে মনে করি +যদিও।
তাইমন

1
আপনি কেন কেবল foo পদ্ধতিটি সংজ্ঞায়িত করবেন না: মুদ্রণ 'বার:' + স্ট (জেটা)?
ইঞ্জিনিয়ারউইথজবা

@ ইঞ্জিনিয়ারউইথজেভা ৫৩৩২২ উদাহরণের জন্য zeta = u"a\xac\u1234\u20ac\U00008000"- সুতরাং print 'bar: ' + unicode(zeta)এটির যাতে ত্রুটি না ঘটে তা নিশ্চিত করতে আপনাকে ব্যবহার করতে হবে। %sএটি সম্পর্কে চিন্তা না করেই ঠিক এটি করা হয় এবং এটি আরও খাটো
ইজকাটা

@ ইঞ্জিনিয়ারউইথজেভা ৫৩৩২২২ অন্যান্য উদাহরণগুলি এখানে কম প্রাসঙ্গিক, তবে উদাহরণস্বরূপ, অন্য কোনও ভাষায় "bar: %s"অনুবাদ করা যেতে পারে "zrb: %s br"%sসংস্করণ মাত্র কাজ, কিন্তু স্ট্রিং-CONCAT সংস্করণ একটি জগাখিচুড়ি সব ক্ষেত্রেই হ্যান্ডেল করতে হবে এবং আপনার অনুবাদকদের এখন মোকাবেলা করার দুটি পৃথক অনুবাদের হবে হবে
Izkata

যদি তারা foo এর বাস্তবায়ন কী তা না জানে তবে তারা যে কোনওটির সাথে এই ত্রুটিতে চলে আসবে def
insidein

3

আমি একটি দ্রুত পরীক্ষা করেছি:

import sys

str = e = "a xxxxxxxxxx very xxxxxxxxxx long xxxxxxxxxx string xxxxxxxxxx\n"

for i in range(int(sys.argv[1])):
    str = str + e

এবং এটি সময়সীমা:

mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  8000000
8000000 times

real    0m2.165s
user    0m1.620s
sys     0m0.540s
mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  16000000
16000000 times

real    0m4.360s
user    0m3.480s
sys     0m0.870s

স্পষ্টতই a = a + bমামলার একটি অপ্টিমাইজেশন রয়েছে । এটি সন্দেহজনক হিসাবে O (n time 2) সময় প্রদর্শন করে না।

কমপক্ষে পারফরম্যান্সের ক্ষেত্রে, ব্যবহার +করা ভাল।


3
আপনি এখানে "যোগদান" কেসের সাথে তুলনা করতে পারেন। এবং অন্যান্য পাইথন বাস্তবায়নের বিষয়টি রয়েছে, যেমন পাইপি, জাইথন, আয়রনপ্যাথন ইত্যাদি ...
jsbueno

3

পাইথন ডক্স অনুসারে, str.join () ব্যবহার করা আপনাকে পাইথনের বিভিন্ন বাস্তবায়ন জুড়ে পারফরম্যান্সের ধারাবাহিকতা দেবে। সিপিথন যদিও s = s + টি এর চতুর্ভুজ আচরণকে অপ্টিমাইজ করেছে, অন্য পাইথন বাস্তবায়ন নাও করতে পারে।

সিপথন বাস্তবায়ন বিশদ : যদি s এবং t উভয় স্ট্রিং হয় তবে কিছু পাইথন বাস্তবায়ন যেমন সিপিথন সাধারণত s = s + t বা s + = t ফর্মের কার্যকারিতা জন্য একটি স্থান-স্থিত অপ্টিমাইজেশন সম্পাদন করতে পারে। প্রযোজ্য হলে, এই অপ্টিমাইজেশানটি চতুর্ভুজ রান-সময়কে খুব কম সম্ভাবনা তৈরি করে। এই অপ্টিমাইজেশনটি সংস্করণ এবং বাস্তবায়ন উভয়ই নির্ভর। পারফরম্যান্স সংবেদনশীল কোডের জন্য, স্ট্রিং জোন () পদ্ধতিটি ব্যবহার করা ভাল which যা সংস্করণ এবং বাস্তবায়ন জুড়ে সুসংগত রৈখিক কনটেন্টেশন পারফরম্যান্সকে আশ্বাস দেয়।

পাইথন ডক্সে সিকোয়েন্স প্রকারগুলি (পাদটীকা দেখুন [6])



0

'' .জয়েন ([a, b]) + এর চেয়ে ভাল সমাধান ।

কারণ কোডটি এমনভাবে লেখা উচিত যা পাইথনের অন্যান্য প্রয়োগগুলি (পাইপাই, জাইথন, আয়রন পাইথন, সাইথন, সাইকো এবং এ জাতীয়) এর ক্ষতি করতে না পারে

ফর্ম a + = b বা a = a + b সিপিথনে এমনকি ভঙ্গুর এবং বাস্তবায়নগুলিতে একেবারেই উপস্থিত নেই যা রি- কাউন্টিং ব্যবহার করে না (রেফারেন্স গণনা একটি রেফারেন্স, পয়েন্টার বা হ্যান্ডলগুলি সংখ্যার সঞ্চয় করার কৌশল is সংস্থান যেমন কোনও বস্তু, মেমরির ব্লক, ডিস্কের স্থান বা অন্যান্য সংস্থান )

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


1
a += bপাইথনের সমস্ত বাস্তবায়নে কাজ করে, এটি কেবলমাত্র লুপের অভ্যন্তরে যখন কিছু করা হয় তখন এটি দ্বিঘাতের সময় নেয় ; প্রশ্নটি ছিল একটি লুপের বাইরে স্ট্রিং কনটেনটেশন সম্পর্কে ।
টায়মন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.