পাইথনে আমি কীভাবে একটি স্ট্রিং যুক্ত করতে পারি?


593

নিম্নলিখিতটি বাদে পাইথনে অন্য একটি স্ট্রিং যুক্ত করার জন্য আমি একটি দক্ষ উপায় চাই।

var1 = "foo"
var2 = "bar"
var3 = var1 + var2

ব্যবহারের জন্য কি কোনও ভাল অন্তর্নির্মিত পদ্ধতি আছে?


8
টিএল; ডিআর: আপনি যদি কেবল স্ট্রিংগুলি যুক্ত করার সহজ উপায়টি সন্ধান করেন, এবং আপনি দক্ষতার কোনও যত্ন নেই:"foo" + "bar" + str(3)
অ্যান্ড্রু

উত্তর:


609

যদি আপনার কাছে কেবল একটি স্ট্রিংয়ের একটি রেফারেন্স থাকে এবং আপনি অন্য স্ট্রিংটি শেষের দিকে একত্রিত করেন, সিপিথন এখন এটি বিশেষ মামলা করে এবং স্ট্রিংটি স্থানে প্রসারিত করার চেষ্টা করে।

শেষ ফলাফলটি হ'ল অপারেশনটি এমোরিটাইজড ও (এন) হয়।

যেমন

s = ""
for i in range(n):
    s+=str(i)

ও (এন ^ 2) হিসাবে ব্যবহৃত হত, তবে এখন এটি ও (এন)।

উত্স থেকে (bytesobject.c):

void
PyBytes_ConcatAndDel(register PyObject **pv, register PyObject *w)
{
    PyBytes_Concat(pv, w);
    Py_XDECREF(w);
}


/* The following function breaks the notion that strings are immutable:
   it changes the size of a string.  We get away with this only if there
   is only one module referencing the object.  You can also think of it
   as creating a new string object and destroying the old one, only
   more efficiently.  In any case, don't use this if the string may
   already be known to some other part of the code...
   Note that if there's not enough memory to resize the string, the original
   string object at *pv is deallocated, *pv is set to NULL, an "out of
   memory" exception is set, and -1 is returned.  Else (on success) 0 is
   returned, and the value in *pv may or may not be the same as on input.
   As always, an extra byte is allocated for a trailing \0 byte (newsize
   does *not* include that), and a trailing \0 byte is stored.
*/

int
_PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
{
    register PyObject *v;
    register PyBytesObject *sv;
    v = *pv;
    if (!PyBytes_Check(v) || Py_REFCNT(v) != 1 || newsize < 0) {
        *pv = 0;
        Py_DECREF(v);
        PyErr_BadInternalCall();
        return -1;
    }
    /* XXX UNREF/NEWREF interface should be more symmetrical */
    _Py_DEC_REFTOTAL;
    _Py_ForgetReference(v);
    *pv = (PyObject *)
        PyObject_REALLOC((char *)v, PyBytesObject_SIZE + newsize);
    if (*pv == NULL) {
        PyObject_Del(v);
        PyErr_NoMemory();
        return -1;
    }
    _Py_NewReference(*pv);
    sv = (PyBytesObject *) *pv;
    Py_SIZE(sv) = newsize;
    sv->ob_sval[newsize] = '\0';
    sv->ob_shash = -1;          /* invalidate cached hash value */
    return 0;
}

অনুগতভাবে যাচাই করার পক্ষে এটি যথেষ্ট সহজ।

x পাইথন-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (10): এস + = 'এ'"
1000000 লুপস, 3 টির মধ্যে সেরা: 1.85 লুপ প্রতি ইউজেক
x পাইথন-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (100): এস + = 'এ'"
10000 লুপস, 3 লুপের জন্য 16: 16 ইউএসসি সেরা
x পাইথন-মি টাইমিটিট-এস "এস = ''" "আই এক্সরেঞ্জে (1000): এস + = 'এ'"
10000 লুপ, প্রতি লুপে 3: 158 ইউএসসি সেরা
x পাইথন-মি টাইমিটিট-এস "এস = ''" "আই এক্সরেঞ্জে (10000): এস + = 'এ'"
1000 লুপগুলি, প্রতি লুপে 3: 1.71 মেকসেটের সেরা
x পাইথন-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (100000): এস + = 'এ'"
10 লুপ, 3 লুপের মধ্যে 14: 14 ম্যাস্কের মধ্যে সেরা
x পাইথন-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (1000000): এস + = 'এ'"
10 লুপগুলি, প্রতি লুপে 3: 173 এমসির মধ্যে সেরা

এটা গুরুত্বপূর্ণ নোট তবে যে এই অপ্টিমাইজেশান পাইথন বৈশিষ্ট অংশ নয়। এটি কেবলমাত্র পাইপথন বাস্তবায়নে যতদূর আমি জানি। উদাহরণস্বরূপ পাইপী বা জাইথনের উপর একই অভিজ্ঞতামূলক পরীক্ষণটি পুরানো ও (এন ** 2) এর পারফরম্যান্সটি দেখায়।

yp পাইপি-এম টাইমিট -s "এস = ''" "আমি এক্সরেঞ্জে (10): এস + = 'এ'"
10000 লুপ, লুপ প্রতি 3: 90.8 ইউজেকের সেরা
x পিঞ্জি-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (100): এস + = 'এ'"
1000 লুপ, প্রতি লুপে 3: 896 ইউএসসি সেরা
x পিঞ্জি-এম টাইমিট -s "এস = ''" "আমি এক্সরেঞ্জে (1000): এস + = 'এ'"
100 লুপগুলি, প্রতি লুপে 3: 9.03 এমসির মধ্যে সেরা
x পিঞ্জি-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (10000): এস + = 'এ'"
10 লুপগুলি, প্রতি লুপে 3: 89.5 ম্যাস্কের মধ্যে সেরা

এখন পর্যন্ত এত ভাল, কিন্তু তারপর,

x পিঞ্জি-মি টাইমিটিট-এস "এস = ''" "আমি এক্সরেঞ্জে (100000): এস + = 'এ'"
10 লুপ, প্রতি লুপে 3: 12.8 সেকেন্ডের মধ্যে সেরা

চতুর্ভুজ এর চেয়েও খারাপ worse সুতরাং পাইপি এমন কিছু করছে যা সংক্ষিপ্ত স্ট্রিংয়ের সাথে ভালভাবে কাজ করে তবে বড় স্ট্রিংয়ের জন্য খারাপ কাজ করে।


14
মজাদার. "এখন" দ্বারা, আপনি কি পাইথন 3.x বলতে চান?
স্টিভ জাজো

10
@ স্টিভ, না। এটি কমপক্ষে 2.6 এও হতে পারে 2.5
জন লা রুই

8
আপনি PyString_ConcatAndDelফাংশনটি উদ্ধৃত করেছেন তবে এর জন্য মন্তব্যটি অন্তর্ভুক্ত করেছেন _PyString_Resize। এছাড়াও, মন্তব্যটি বিগ-ও সম্পর্কিত আপনার দাবীটি সত্যই প্রতিষ্ঠিত করে না
উইনস্টন ইওয়ার্ট

3
সিপিথন বৈশিষ্ট্যটি কাজে লাগানোর জন্য অভিনন্দন যা কোডটি অন্যান্য প্রয়োগের ক্ষেত্রে ক্রল করবে। খারাপ পরামর্শ।
জিন-ফরাসোইস ফ্যাব্রে

4
এটি ব্যবহার করবেন না। পেপ 8 স্পষ্ট করে বলেছে: কোডটি এমনভাবে লেখা উচিত যাতে পাইথনের অন্যান্য প্রয়োগগুলি (পাইপাই, জাইথন, আয়রন পাইথন, সাইথন, সাইকো এবং অন্যান্য) এর ক্ষতি হয় না , এটি এতো ভঙ্গুর হওয়ার কারণে এড়াতে এটিকে নির্দিষ্ট উদাহরণ হিসাবে দেয় ter আরও ভাল ব্যবহার"".join(str_a, str_b)
23:43

287

অকালে অপটিমাইজ করবেন না। আপনার যদি বিশ্বাস করার কোনও কারণ না থাকে যে স্ট্রিং কনটেন্টেশনের কারণে গতির বাধা রয়েছে তবে কেবল +এবং এর সাথে আটকে থাকুন +=:

s  = 'foo'
s += 'bar'
s += 'baz'

এটি বলেছিল, আপনি যদি জাভার স্ট্রিংবিল্ডারের মতো কোনও কিছুর সন্ধান করছেন, তবে ক্যানোনিকাল পাইথন আইডিয়মটি তালিকায় আইটেম যুক্ত করতে হবে এবং তারপরে সবগুলি সংক্ষেপে ব্যবহার str.joinকরতে হবে:

l = []
l.append('foo')
l.append('bar')
l.append('baz')

s = ''.join(l)

আমি জানি না যে আপনার স্ট্রিংগুলি তালিকাগুলি হিসাবে তৈরি করার পরে এবং সেগুলিতে যোগ দিন () এগুলি কী তা গতিতে প্রভাব ফেলতে পারে তবে আমি দেখতে পাই এটি সাধারণত সবচেয়ে পরিষ্কার উপায়। আমি লিখেছি এমন এসকিউএল টেম্প্লেটিং ইঞ্জিনের জন্য একটি স্ট্রিংয়ের মধ্যে% s স্বরলিপি ব্যবহার করার ক্ষেত্রেও আমি বড় সাফল্য পেয়েছি।
ধনী

25
@ রিচো .join ব্যবহার করা আরও কার্যকর is কারণটি হচ্ছে পাইথন স্ট্রিংগুলি পরিবর্তনযোগ্য নয়, তাই বারবার s + = আরও ব্যবহার করার ফলে প্রচুর পরিমাণে বৃহত্তর স্ট্রিং বরাদ্দ হবে। .জয়িন তার উপাদানগুলির অংশ থেকে একসাথে চূড়ান্ত স্ট্রিং তৈরি করবে।
বেন

5
@ বেন, এই অঞ্চলে একটি উল্লেখযোগ্য উন্নতি হয়েছে - আমার উত্তর দেখুন
জন লা রুয়

41
str1 = "Hello"
str2 = "World"
newstr = " ".join((str1, str2))

এটি বিভাজক হিসাবে একটি স্থানের সাথে str1 এবং str2 এ যোগ দেয়। আপনি করতে পারেন "".join(str1, str2, ...)str.join()একটি পুনরাবৃত্তযোগ্য লাগে, সুতরাং আপনি একটি তালিকা বা একটি tuple মধ্যে স্ট্রিং রাখতে হবে।

এটি বিল্টিন পদ্ধতির জন্য যতটা দক্ষ তা প্রায় কার্যকর।


কি হবে, যদি str1 খালি থাকে? সাদা স্থান সেট করা হবে?
জর্জেন কে।

38

না।

এটি হ'ল বেশিরভাগ ক্ষেত্রে আপনি বিদ্যমান স্ট্রিংয়ের সাথে যুক্ত হয়ে এক সাথে পুরো স্ট্রিং তৈরি করা ভাল better

উদাহরণস্বরূপ, করবেন না: obj1.name + ":" + str(obj1.count)

পরিবর্তে: ব্যবহার "%s:%d" % (obj1.name, obj1.count)

এটি পড়া সহজ এবং আরও দক্ষ হবে।


54
আমি দুঃখিত, প্রথম উদাহরণের মতো (স্ট্রিং + স্ট্রিং) এর চেয়ে বেশি সহজ পাঠের আর কিছুই নেই, দ্বিতীয় উদাহরণটি আরও দক্ষ হতে পারে তবে বেশি পঠনযোগ্য নয়
JqueryToAddNumbers

23
@ এক্সসেপশনস্লেয়ার, স্ট্রিং + স্ট্রিং অনুসরণ করা বেশ সহজ। তবে "<div class='" + className + "' id='" + generateUniqueId() + "'>" + message_text + "</div>", আমি তখন কম পঠনযোগ্য এবং ত্রুটি-প্রবণ খুঁজে পাই"<div class='{classname}' id='{id}'>{message_text}</div>".format(classname=class_name, message_text=message_text, id=generateUniqueId())
উইনস্টন ইওয়ার্ট

পিএইচপি / পার্লের "স্ট্রিং। = যাচাইডাটা ()" বা এর মতোই এর সমপরিমাণ যখন আমি যা করার চেষ্টা করে যাচ্ছি এটি কখনই সহায়তা করে না।
শাদুর

@ শাদুর, আমার বক্তব্যটি আপনার আবার চিন্তা করা উচিত, আপনি কি সত্যই সমমানের কিছু করতে চান, বা সম্পূর্ণ ভিন্ন পদ্ধতির চেয়ে ভাল?
উইনস্টন ইওয়ার্ট

1
এবং এই ক্ষেত্রে এই প্রশ্নের উত্তর "না, কারণ যে পদ্ধতিটি আমার ব্যবহারের ক্ষেত্রে আবরণ দেয় না"
শাদুর

11

পাইথন ৩.6 আমাদের এফ স্ট্রিং দেয় যা একটি আনন্দের বিষয়:

var1 = "foo"
var2 = "bar"
var3 = f"{var1}{var2}"
print(var3)                       # prints foobar

আপনি কোঁকড়া ধনুর্বন্ধনী এর ভিতরে সর্বাধিক কিছু করতে পারেন

print(f"1 + 1 == {1 + 1}")        # prints 1 + 1 == 2

10

বড় স্ট্রিং তৈরি করতে আপনার যদি অনেক অ্যাপেনড অপারেশন করতে হয় তবে আপনি স্ট্রিংআইও বা সিস্ট্রিংআইও ব্যবহার করতে পারেন । ইন্টারফেসটি একটি ফাইলের মতো। যেমন: আপনি writeএটিতে পাঠ্য যোগ করতে পারেন।

আপনি যদি কেবল দুটি স্ট্রিং যুক্ত করে থাকেন তবে কেবল ব্যবহার করুন +


9

এটি সত্যিই আপনার আবেদনের উপর নির্ভর করে। আপনি যদি কয়েকশ শব্দের মধ্য দিয়ে লুপ করছেন এবং সেগুলি একটি তালিকায় যুক্ত করতে চান .join()তবে আরও ভাল। তবে আপনি যদি দীর্ঘ দীর্ঘ বাক্য একসাথে রাখছেন তবে আপনি ব্যবহার করা ভাল +=


5

মূলত, কোনও পার্থক্য নেই। একমাত্র ধারাবাহিক প্রবণতা হ'ল পাইথন প্রতিটি সংস্করণের সাথে ধীর হয়ে যাচ্ছে ... :(


তালিকা

%%timeit
x = []
for i in range(100000000):  # xrange on Python 2.7
    x.append('a')
x = ''.join(x)

পাইথন 2.7

1 লুপ, প্রতি লুপ 3: 7.34 এর মধ্যে সেরা

পাইথন ৩.৪

1 লুপ, প্রতি লুপ 3: 7.99 এর মধ্যে সেরা

পাইথন ৩. 3.5

1 লুপ, প্রতি লুপে 3: 8.48 এর মধ্যে সেরা

পাইথন ৩.6

1 লুপ, প্রতি লুপ 3: 9.93 এস এর মধ্যে সেরা


দড়ি

%%timeit
x = ''
for i in range(100000000):  # xrange on Python 2.7
    x += 'a'

পাইথন ২.7 :

1 লুপ, প্রতি লুপ 3: 7.41 এর মধ্যে সেরা

পাইথন ৩.৪

1 লুপ, প্রতি লুপ 3: 9.08 এর মধ্যে সেরা

পাইথন ৩. 3.5

1 লুপ, প্রতি লুপে 3: 8.82 এর মধ্যে সেরা

পাইথন ৩.6

1 লুপ, প্রতি লুপ 3: 9.24 এস এর মধ্যে সেরা


2
আমার ধারণা এটি নির্ভর করে। আমি পেতে 1.19 sএবং 992 msPython2.7 উপর যথাক্রমে
জন লা রয়


2
a='foo'
b='baaz'

a.__add__(b)

out: 'foobaaz'

1
কোডটি দুর্দান্ত, তবে এটির সাথে একটি ব্যাখ্যা দিতে সহায়তা করবে। এই পৃষ্ঠায় অন্যান্য উত্তরগুলির চেয়ে এই পদ্ধতিটি কেন ব্যবহার করবেন?
সিজিবিএম

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