Bagaimana saya menambahkan satu string yang lain di Python?

Saya ingin cara yang efisien untuk menambahkan satu string yang lain di Python, selain sebagai berikut.

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

Apa ada metode built-in untuk digunakan?

Mengomentari pertanyaan (1)
Larutan

Jika anda hanya memiliki satu referensi untuk sebuah string dan anda menggabungkan string lain sampai akhir, CPython sekarang kasus-kasus khusus ini dan mencoba untuk memperpanjang string di tempat.

Hasil akhirnya adalah bahwa operasi diamortisasi O(n).

misalnya

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

digunakan untuk menjadi O(n^2), tapi sekarang itu adalah O(n).

Dari sumber (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;
}

It's cukup mudah untuk verifikasi secara empiris.

$ python -m waktuhal -s"s=''", "bagi saya di xrange(10):s+='a',"
1000000 loop, terbaik dari 3: 1.85 usec per loop
$ python -m waktuhal -s"s=''", "bagi saya di xrange(100):s+='a',"
10000 loop, terbaik dari 3: 16.8 usec per loop
$ python -m waktuhal -s"s=''", "bagi saya di xrange(1000):s+='a',"
10000 loop, terbaik dari 3: 158 usec per loop
$ python -m waktuhal -s"s=''", "bagi saya di xrange(10000):s+='a',"
1000 loop, terbaik dari 3: 1.71 msec per loop
$ python -m waktuhal -s"s=''", "bagi saya di xrange(100000):s+='a',"
10 loop, terbaik dari 3: 14.6 msec per loop
$ python -m waktuhal -s"s=''", "bagi saya di xrange(1000000):s+='a',"
10 loop, terbaik dari 3: 173 msec per loop

It's penting namun untuk dicatat bahwa ini optimasi isn't bagian dari Python spec. It's hanya di cPython implementasi sejauh yang saya tahu. Sama empiris pengujian di mount atau kelompok dari setiap dua elemen misalnya mungkin menunjukkan lebih tua O(n**2) kinerja .

$ mount -m waktuhal -s"s=''", "bagi saya di xrange(10):s+='a',"
10000 loop, terbaik dari 3: 90.8 usec per loop
$ mount -m waktuhal -s"s=''", "bagi saya di xrange(100):s+='a',"
1000 loop, terbaik dari 3: 896 usec per loop
$ mount -m waktuhal -s"s=''", "bagi saya di xrange(1000):s+='a',"
100 loop, terbaik dari 3: 9.03 msec per loop
$ mount -m waktuhal -s"s=''", "bagi saya di xrange(10000):s+='a',"
10 loop, terbaik dari 3: 89.5 msec per loop

So far So good, tapi kemudian,

$ mount -m waktuhal -s"s=''", "bagi saya di xrange(100000):s+='a',"
10 loop, terbaik dari 3: 12.8 detik per loop

aduh bahkan lebih buruk dari kuadrat. Jadi mount adalah melakukan sesuatu yang bekerja dengan baik dengan string pendek, tapi melakukan buruk untuk string yang lebih besar.

Komentar (6)

Don't prematur mengoptimalkan. Jika anda tidak memiliki alasan untuk percaya ada's kecepatan angin dan hambatan yang disebabkan oleh penggabungan string maka hanya dengan tongkat + dan +=:

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

Yang mengatakan, jika anda're bertujuan untuk sesuatu seperti Java's StringBuilder, kanonik Python idiom adalah untuk menambahkan item ke daftar, dan kemudian menggunakan str.bergabung dengan menyatukan mereka semua di akhir:

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

s = ''.join(l)
Komentar (3)

Don't.

Itu adalah, untuk sebagian besar kasus, anda akan lebih baik menghasilkan seluruh string dalam satu pergi agak kemudian menambahkan ke yang sudah ada string.

Misalnya, don't melakukan: obj1.nama + ":" + str(obj1.count)

Bukan: gunakan "%s:%d" % (obj1.nama, obj1.count)

Sehingga akan lebih mudah untuk membaca dan lebih efisien.

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

Yang bergabung str1 dan str2 dengan spasi sebagai pemisah. Anda juga dapat melakukan "".bergabung(str1, str2, ...). str.join() mengambil iterable, sehingga anda'd harus menempatkan string di dalam suatu daftar atau tupel.

Yang's tentang seefisien mendapat builtin metode.

Komentar (1)

Jika anda perlu untuk melakukan banyak menambahkan operasi besar untuk membangun sebuah string, anda dapat menggunakan StringIO atau cStringIO. Antarmuka seperti file. yaitu: anda menulis untuk menambahkan teks ke dalamnya.

Jika anda're hanya menambahkan dua string kemudian hanya menggunakan +.

Komentar (0)

itu benar-benar tergantung pada aplikasi anda. Jika anda're perulangan melalui ratusan kata-kata dan ingin menambahkan mereka semua ke dalam sebuah daftar, .join() adalah baik. Tapi jika anda're menyusun kalimat panjang, anda're lebih baik menggunakan +=.

Komentar (0)

Python 3.6 memberi kita f-string, yang menyenangkan:

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

Anda dapat melakukan apa yang paling di dalam kurung kurawal

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

Pada dasarnya, tidak ada perbedaan. Satu-satunya yang konsisten tren adalah bahwa Python tampaknya akan semakin lambat dengan setiap versi... :(


Daftar

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

Python 2.7

1 loop, terbaik 3: 7.34 s per loop

Python 3.4

1 loop, terbaik 3: 7.99 s per loop

Python 3.5

1 loop, terbaik 3: 8.48 s per loop

Python 3.6

1 loop, terbaik 3: 9.93 s per loop


String

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

Python 2.7:

1 loop, terbaik dari 3: 7.41 s per loop

Python 3.4

1 loop, terbaik 3: 9.08 s per loop

Python 3.5

1 loop, terbaik 3: 8.82 s per loop

Python 3.6

1 loop, terbaik 3: 9.24 s per loop

Komentar (1)
a='foo'
b='baaz'

a.__add__(b)

out: 'foobaaz'
Komentar (2)

append string dengan add fungsi

str = "Hello"
str2 = " World"
st = str.__add__(str2)
print(st)

Output

Hello World
Komentar (1)