পাইথনে স্ট্রিং কনটেনটেশন বনাম স্ট্রিং প্রতিস্থাপন


98

পাইথনে, স্ট্রিং কনটেনটেশন বনাম স্ট্রিং প্রতিস্থাপনের ব্যবহারটি আমাকে কখন এবং কখনই সরিয়ে দেয়। যেহেতু স্ট্রিং কনটেনটেশন কর্মক্ষমতাতে বড় উত্সাহ দেখেছে, এটি কি (বাস্তবতর হয়ে) বাস্তবের পরিবর্তে একটি স্টাইলিস্টিক সিদ্ধান্ত?

একটি দৃ concrete় উদাহরণের জন্য, কীভাবে কোনওটিকে নমনীয় ইউআরআই নির্মাণ করতে হবে:

DOMAIN = 'http://stackoverflow.com'
QUESTIONS = '/questions'

def so_question_uri_sub(q_num):
    return "%s%s/%d" % (DOMAIN, QUESTIONS, q_num)

def so_question_uri_cat(q_num):
    return DOMAIN + QUESTIONS + '/' + str(q_num)

সম্পাদনা করুন: স্ট্রিংয়ের তালিকায় যোগদানের জন্য এবং নামযুক্ত প্রতিস্থাপন ব্যবহার করার বিষয়েও পরামর্শ দেওয়া হয়েছে। এগুলি কেন্দ্রীয় থিমের রূপগুলি, যা কোন সময়ে এটি করার সঠিক উপায় কোনটি? প্রতিক্রিয়া জন্য ধন্যবাদ!


মজাদার, রুবিতে স্ট্রিং ইন্টারপোলেশনটি সাধারণত
কনটেনটেশনের

আপনি ফিরে "" জয়েন (ভুলে গেছেন। "([ওবাম, ক্যোস্টশনস, টিআরটি (কিউএনএন)))
জিমি

আমি কোনও রুবি বিশেষজ্ঞ নই, তবে আমি বাজি ধরব যে ইন্টারপোলেশন দ্রুত হয় কারণ রুবিতে স্ট্রিংগুলি পরিবর্তনযোগ্য। স্ট্রিংগুলি পাইথনের অপরিবর্তনীয় ক্রম।

4
ইউআরআই সম্পর্কে কেবল একটি সামান্য মন্তব্য। ইউআরআইগুলি হুবহু স্ট্রিংয়ের মতো নয়। সেখানে ইউআরআই রয়েছে, সুতরাং আপনি যখন তাদের সাথে একত্রীকরণ বা তুলনা করবেন তখন আপনাকে খুব সতর্কতা অবলম্বন করতে হবে। উদাহরণ: ৮০ পোর্টে HTTP- র মাধ্যমে একটি উপস্থাপনা সরবরাহকারী একটি সার্ভার উদাহরণস্বরূপ (শেষ দিকে কোনও স্ল্যাশ নয়) উদাহরণ.org/ (স্ল্যাশ) example.org:80/ (স্ল্যাহ + পোর্ট 80) একই ইউরি তবে একই নয় স্ট্রিং
কার্লকো

উত্তর:


55

কনটেনটেশন (উল্লেখযোগ্যভাবে) আমার মেশিন অনুসারে দ্রুত। তবে স্টাইলিস্টিকভাবে, আমি যদি পারফরম্যান্সের সমালোচনা না করে তবে প্রতিস্থাপনের মূল্য দিতে রাজি আছি। ঠিক আছে, এবং যদি আমার ফর্ম্যাটিং প্রয়োজন হয়, এমনকি এমনকি প্রশ্ন জিজ্ঞাসা করারও দরকার নেই ... ইন্টারপোলেশন / টেম্প্লেটিং ব্যবহার করা ছাড়া বিকল্প নেই।

>>> import timeit
>>> def so_q_sub(n):
...  return "%s%s/%d" % (DOMAIN, QUESTIONS, n)
...
>>> so_q_sub(1000)
'http://stackoverflow.com/questions/1000'
>>> def so_q_cat(n):
...  return DOMAIN + QUESTIONS + '/' + str(n)
...
>>> so_q_cat(1000)
'http://stackoverflow.com/questions/1000'
>>> t1 = timeit.Timer('so_q_sub(1000)','from __main__ import so_q_sub')
>>> t2 = timeit.Timer('so_q_cat(1000)','from __main__ import so_q_cat')
>>> t1.timeit(number=10000000)
12.166618871951641
>>> t2.timeit(number=10000000)
5.7813972166853773
>>> t1.timeit(number=1)
1.103492206766532e-05
>>> t2.timeit(number=1)
8.5206360154188587e-06

>>> def so_q_tmp(n):
...  return "{d}{q}/{n}".format(d=DOMAIN,q=QUESTIONS,n=n)
...
>>> so_q_tmp(1000)
'http://stackoverflow.com/questions/1000'
>>> t3= timeit.Timer('so_q_tmp(1000)','from __main__ import so_q_tmp')
>>> t3.timeit(number=10000000)
14.564135316080637

>>> def so_q_join(n):
...  return ''.join([DOMAIN,QUESTIONS,'/',str(n)])
...
>>> so_q_join(1000)
'http://stackoverflow.com/questions/1000'
>>> t4= timeit.Timer('so_q_join(1000)','from __main__ import so_q_join')
>>> t4.timeit(number=10000000)
9.4431309007150048

10
আপনি কি সত্যিকারের বড় স্ট্রিং (100000 টি অক্ষরের মতো) দিয়ে পরীক্ষা করেছেন?
মাতাল

24

নামকৃত প্রতিস্থাপন সম্পর্কে ভুলবেন না:

def so_question_uri_namedsub(q_num):
    return "%(domain)s%(questions)s/%(q_num)d" % locals()

4
এই কোডটিতে কমপক্ষে দুটি খারাপ প্রোগ্রামিং অনুশীলন রয়েছে: গ্লোবাল ভেরিয়েবলের প্রত্যাশা (ফাংশনের অভ্যন্তরে ডোমেন এবং প্রশ্নগুলি ঘোষিত হয় না) এবং একটি ফর্ম্যাট () ফাংশনে প্রয়োজনের চেয়ে বেশি ভেরিয়েবল পাস করা। ডাউনভোটিং কারণ এই উত্তরটি খারাপ কোডিং অনুশীলনগুলি শেখায়।
jperelli

12

একটি লুপে কনটেনেটিং স্ট্রিং সম্পর্কে সতর্ক থাকুন! স্ট্রিং কনটেনটেশনের ব্যয় ফলাফলের দৈর্ঘ্যের সমানুপাতিক। লুপিং আপনাকে সরাসরি এন-স্কোয়ারের ভূমিতে নিয়ে যায়। কিছু ভাষাগুলি সর্বাধিক বরাদ্দ স্ট্রিংটিতে কনটেনটেশনকে অনুকূল করে তুলবে, তবে আপনার চতুর্ভুজ অ্যালগরিদমকে রৈখিকের তুলনায় কমপিউটারের মধ্যে নির্ভর করা ঝুঁকিপূর্ণ। আদিম ( join?) ব্যবহারের জন্য সর্বোত্তম যা স্ট্রিংগুলির পুরো তালিকাটি নেয়, একটি একক বরাদ্দ করে এবং একসাথে সবগুলি সংক্ষিপ্ত করে।


16
এটি বর্তমান নয় not পাইথনের সর্বশেষতম সংস্করণগুলিতে, যখন আপনি একটি লুপে স্ট্রিংগুলি সংহত করেন তখন একটি গোপন স্ট্রিং বাফার তৈরি হয়।
Seun Osewa

5
@ শিউন: হ্যাঁ, যেমনটি আমি বলেছিলাম কিছু ভাষাগুলি অপ্টিমাইজ করবে তবে এটি একটি ঝুঁকিপূর্ণ অনুশীলন।
নরম্যান রামসে

11

"যেহেতু স্ট্রিং কনটেনটেশনে পারফরম্যান্সে বড়ো বৃদ্ধি পেয়েছে ..."

পারফরম্যান্স যদি গুরুত্বপূর্ণ হয় তবে এটি জানা ভাল।

তবে, আমি যে পারফরম্যান্স সমস্যা দেখেছি সেগুলি কখনও স্ট্রিং অপারেশনে নেমে আসে না। আমি সাধারণত I / O, বাছাই এবং O ( n 2 ) অপারেশন বাধা হওয়ায় সমস্যার মধ্যে পড়েছি।

স্ট্রিং অপারেশনগুলি পারফরম্যান্স সীমাবদ্ধ না হওয়া পর্যন্ত আমি স্পষ্টতই সেই জিনিসগুলির সাথে লেগে থাকব। বেশিরভাগ ক্ষেত্রে, এটি প্রতিস্থাপন যখন এটি এক লাইন বা তার চেয়ে কম হয়, যখন তা বোঝায় তখন কনটেন্টেশন এবং যখন বড় হয় তখন একটি টেম্পলেট সরঞ্জাম (মাকোর মতো)।


10

আপনি কী যুক্ত করতে / ইন্টারপোলেট করতে চান এবং কীভাবে ফলাফলটি ফর্ম্যাট করতে চান তা আপনার সিদ্ধান্তকে চালিত করবে।

  • স্ট্রিং ইন্টারপোলেশন আপনাকে সহজেই ফরম্যাটিং যুক্ত করতে দেয়। প্রকৃতপক্ষে, আপনার স্ট্রিং ইন্টারপোলেশন সংস্করণ আপনার কনটেক্সটেশন সংস্করণ হিসাবে একই কাজ করে না; এটি q_numপ্যারামিটারের আগে একটি অতিরিক্ত ফরোয়ার্ড স্ল্যাশ যুক্ত করে । একই জিনিসটি করতে, আপনাকে return DOMAIN + QUESTIONS + "/" + str(q_num)সেই উদাহরণে লিখতে হবে ।

  • ইন্টারপোলেশন সংখ্যার ফর্ম্যাট করা সহজ করে; "%d of %d (%2.2f%%)" % (current, total, total/current)সংমিশ্রণ আকারে খুব কম পাঠযোগ্য হবে।

  • কনক্রিটেশন কার্যকর যখন আপনার কাছে স্ট্রিং-আইজে আইটেমগুলির একটি নির্দিষ্ট সংখ্যা না থাকে।

এছাড়াও, জেনে রাখুন যে পাইথন ২.6 স্ট্রিং ইন্টারপোলেশনের একটি নতুন সংস্করণ প্রবর্তন করে, যাকে বলা হয় স্ট্রিং টেম্প্লেটিং :

def so_question_uri_template(q_num):
    return "{domain}/{questions}/{num}".format(domain=DOMAIN,
                                               questions=QUESTIONS,
                                               num=q_num)

স্ট্রিং টেম্প্লেটিং অবশেষে% -interpolation প্রতিস্থাপন করা হবে, কিন্তু এটি বেশ কিছুদিনের জন্য ঘটবে না, আমি মনে করি।


ঠিক আছে, যখনই আপনি অজগর 3.0 এ যাওয়ার সিদ্ধান্ত নেবেন তখনই এটি ঘটবে। এছাড়াও, আপনি যে কোনওভাবে% অপারেটরের সাথে নামযুক্ত বিকল্পগুলি করতে পারেন এই জন্য পিটারের মন্তব্য দেখুন।
জন ফুহি

"আপনার কাছে স্ট্রিং-আইসে নির্দিষ্ট সংখ্যক আইটেম না থাকলে কনকাটেনেশন কার্যকর হয়।" - আপনি একটি তালিকা / অ্যারে মানে? সেক্ষেত্রে আপনি কি তাদের সাথে যোগ দিতে পারবেন না?
স্টারগার

"আপনি কি তাদের সাথে যোগ দিতে পারবেন না?" - হ্যাঁ (ধরে নিচ্ছেন আইটেমগুলির মধ্যে আপনি অভিন্ন বিভাজক চান)। তালিকা এবং জেনারেটর বোঝাপড়া স্ট্রিং.জাইন সহ দুর্দান্ত কাজ করে।
টিম লেশার

4
"ঠিক আছে, যখনই আপনি পাইথন ৩.০ এ যাওয়ার সিদ্ধান্ত নেবেন" - না, পাই 3 কে এখনও% অপারেটরকে সমর্থন করে। পরবর্তী সম্ভাব্য অবমূল্যায়ন পয়েন্টটি 3.1, সুতরাং এটিতে এখনও কিছুটা জীবন রয়েছে has
টিম লেশার

4
2 বছর পরে ... অজগর 3.2 প্রকাশের কাছাকাছি এবং% শৈলীর অন্তরঙ্গ এখনও ঠিক আছে।
কোরি গোল্ডবার্গ

8

আমি কৌতুহল ছাড়াই কেবল ভিন্ন স্ট্রিং সংশ্লেষ / প্রতিস্থাপন পদ্ধতিগুলির গতি পরীক্ষা করছিলাম। বিষয় সম্পর্কে একটি গুগল অনুসন্ধান আমাকে এখানে এনেছে। আমি ভেবেছিলাম যে আমি আমার পরীক্ষার ফলাফল পোস্ট করব এই আশায় যে এটি কারওর সিদ্ধান্ত নিতে সহায়তা করবে।

    import timeit
    def percent_():
            return "test %s, with number %s" % (1,2)

    def format_():
            return "test {}, with number {}".format(1,2)

    def format2_():
            return "test {1}, with number {0}".format(2,1)

    def concat_():
            return "test " + str(1) + ", with number " + str(2)

    def dotimers(func_list):
            # runs a single test for all functions in the list
            for func in func_list:
                    tmr = timeit.Timer(func)
                    res = tmr.timeit()
                    print "test " + func.func_name + ": " + str(res)

    def runtests(func_list, runs=5):
            # runs multiple tests for all functions in the list
            for i in range(runs):
                    print "----------- TEST #" + str(i + 1)
                    dotimers(func_list)

... দৌড়ানোর পরে runtests((percent_, format_, format2_, concat_), runs=5), আমি দেখতে পেলাম যে% পদ্ধতিটি এই ছোট স্ট্রিংগুলিতে অন্যদের চেয়ে দ্বিগুণ দ্রুত ছিল। কনক্যাট পদ্ধতিটি সর্বদা ধীর (সবে) ছিল। format()পদ্ধতিতে অবস্থানগুলি স্যুইচ করার সময় খুব ছোট পার্থক্য ছিল , তবে অবস্থানগুলি স্যুইচ করা সর্বদা নিয়মিত বিন্যাস পদ্ধতির চেয়ে কমপক্ষে .01 ধীর ছিল।

পরীক্ষার ফলাফলের নমুনা:

    test concat_()  : 0.62  (0.61 to 0.63)
    test format_()  : 0.56  (consistently 0.56)
    test format2_() : 0.58  (0.57 to 0.59)
    test percent_() : 0.34  (0.33 to 0.35)

আমি এগুলি চালিয়েছি কারণ আমি আমার স্ক্রিপ্টগুলিতে স্ট্রিং কনটেনটেশন ব্যবহার করি এবং আমি ভাবছিলাম যে ব্যয়টি কী। কোনও কিছুই হস্তক্ষেপ করছে না, বা ভাল পারফরম্যান্স পাচ্ছে তা প্রথম বা শেষের দিকে তা নিশ্চিত করার জন্য আমি তাদেরকে বিভিন্ন আদেশে চালিয়েছি। পাশের নোটে, আমি এই জাতীয় ফাংশনগুলিতে কিছু দীর্ঘ স্ট্রিং জেনারেটর নিক্ষেপ করেছি "%s" + ("a" * 1024)এবং নিয়মিত কনক্যাটটি প্রায় 3 গুণ দ্রুত (1.1 বনাম 2.8) formatএবং %পদ্ধতিগুলি ব্যবহার করে । আমার ধারণা এটি স্ট্রিংগুলির উপর নির্ভর করে এবং আপনি কী অর্জন করতে চাইছেন trying কর্মক্ষমতা যদি সত্যিই গুরুত্বপূর্ণ হয় তবে বিভিন্ন জিনিস চেষ্টা করে পরীক্ষা করে নেওয়া আরও ভাল better আমি গতির চেয়ে বেশি পঠনযোগ্যতা বেছে নেওয়ার ঝোঁক রেখেছি, যদি না গতি সমস্যা হয়ে দাঁড়ায় তবে কেবল আমাকেই তা জানায়। সুতরাং আমার অনুলিপি / পেস্ট পছন্দ হয়নি, এটিকে সঠিক দেখানোর জন্য আমাকে সবকিছুতে 8 টি স্পেস রাখতে হয়েছিল। আমি সাধারণত 4 ব্যবহার করি।


4
আপনি কীভাবে প্রোফাইল দিচ্ছেন তা গুরুত্ব সহকারে বিবেচনা করা উচিত। একটির জন্য আপনার কনক্যাটটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে আপনার কাছে দুটি স্ট্রিং কাস্ট রয়েছে। স্ট্রিংগুলির সাথে ফলাফলটি বিপরীত হয়, যেহেতু স্ট্রিং কনক্যাটটি কেবলমাত্র তিনটি স্ট্রিংয়ের সাথে সম্পর্কিত তখন সমস্ত বিকল্পের চেয়ে দ্রুত হয়।
জাস্টাস উইঙ্গার্ট

@ জাস্টাস উইঞ্জার্ট, এটি এখন দু'বছর বয়স। আমি এই 'পরীক্ষা' পোস্ট করার পর থেকে আমি অনেক কিছু শিখেছি। সত্যি, এই দিন আমি ব্যবহার str.format()এবং str.join()স্বাভাবিক সংযুক্তকরণের করে। আমি পিইপি 498 থেকে 'এফ-স্ট্রিং'-এর জন্য নজর রাখছি যা সম্প্রতি গৃহীত হয়েছে। হিসাবে str()কর্মক্ষমতা প্রভাবিত কল, আমি নিশ্চিত আপনি যে চলেছেন ঠিক আছি। সেই সময় কত দামি ফাংশন কল ছিল তা আমার কোনও ধারণা ছিল না। আমি এখনও মনে করি যে কোনও সন্দেহ থাকলে পরীক্ষা করা উচিত।
সিজে ওয়েলবোর্ন

দ্রুত পরীক্ষা করার পরে join_(): return ''.join(["test ", str(1), ", with number ", str(2)]), এটি joinশতাংশের চেয়ে ধীর গতির বলে মনে হয়।
চমত্কার

4

মনে রাখবেন, রচনাশৈলীসংক্রান্ত সিদ্ধান্ত হয় , বাস্তব সিদ্ধান্ত যদি কখনও রক্ষণাবেক্ষন ও আপনার কোড ডিবাগ করার পরিকল্পনা :-) আছে Knuth (? সম্ভবত হোয়ারে উদ্ধৃত) থেকে একটি বিখ্যাত উদ্ধৃতি আছে: "আমরা, ছোট দক্ষতাসম্পন্ন সম্পর্কে ভুলে গেলে সময় 97% সম্পর্কে বলে, অকালীন অপটিমাইজেশন হ'ল সমস্ত অশুভের মূল ""

আপনি যতক্ষণ সতর্ক হন (যতক্ষণ না) কোনও ও (এন) টাস্ককে ও (এন 2 ) টাস্কে পরিণত করবেন না, আপনি যাকে বোঝার পক্ষে সবচেয়ে সহজ মনে করি আমি তার সাথে যাব ..


0

আমি যেখানেই পারি বিকল্প ব্যবহার করি use আমি কেবল কনটেনটেশন ব্যবহার করি যদি আমি ফোর-লুপ বলতে একটি স্ট্রিং তৈরি করি।


7
"এ একটি স্ট্রিং নির্মাণের একটি জন্য-লুপ" - প্রায়ই এই একটি ক্ষেত্রে যেখানে আপনি 'ব্যবহার করতে পারেন' .join এবং একটি জেনারেটর অভিব্যক্তি ..
জন Fouhy

-1

আসলে সঠিক জিনিসটি, এক্ষেত্রে (বিল্ডিং পাথ) ব্যবহার করা os.path.join। স্ট্রিং কনটেনটেশন বা ইন্টারপোলেশন নয়


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