Andrii's blog Blog about programming

Can I copy string in Python 3.5? And how?

“Mathematics reveals its secrets only to those who approach it with pure love, for its own beauty.”

― Archimedes

Domenico Fetti Archimedes

Quick introduction

Why do you need to copy a Python strings? It’s interesting question, because Python string is immutable. Also any tries of copy will returns the original string. Python tries to keep just the one copy, as that makes dictionary lookups faster.

May be use slice?

$ python3
Python 3.5.2 (default, Sep 15 2016, 07:38:42)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 'python'
>>> b = a[:]
>>> b = a[:]
>>> id(a), id(b)
(4400931648, 4400931648)

Add empty string? No!

>>> a = 'python'
>>> id(a)
4400931648
>>> b = a + ''
>>> id(b)
4400931648  

Or use str function?

>>> a = 'python'
>>> id(a)
4400931648
>>> b =str(a)
>>> id(b)
4400931648

Try to use copy?

>>> a = 'python'
>>> id(a)
4400931648
>>> import copy
>>> b = copy.copy(a)
>>> id(b)
4400931648

Let’s do deepcopy!

>>> a = 'python'
>>> id(a)
4400931648
>>> b = copy.deepcopy(a)
>>> id(b)
4400931648
>>> print('No chance!')
No chance!

Another tries with using slice?

>>> a = 'python'
>>> b = (a + '.')[:-1]
>>> id(a)
4400931648
>>> id(b)
4400931760
>>> print('Eureka!')
Eureka!

Last try with encode and decode

>>> a = 'python'
>>> id(a)
4400931648
>>> b = a.encode().decode()
>>> b
'python'
>>> id(b)
4400931984
>>> print('Eureka!')
Eureka!

Conclusion

Try to answer the first question:

Can I copy or clone string in Python?

Answer is: no you can’t.

Every time we create new string, both working examples uses the same idea:

>>> a = 'a' * 1024
>>> b = 'a' * 1024
>>> id(a)
140726834891776
>>> id(b)
140726843315712

P.S. Thanks for ideas from Pavel’s talk from PyCon Russian 2016 and some more info you can find in references.

References

A collection of Python "must reads"

Articles:

Books:

Other python must read lists:

How to read input fast in python and transform into ints

Недавно я решал задачу (UVa 10013 - Super long sums), и там я наткнулся на ситуацию, где нужно было максимально быстро читать входные данные.

Т.е о чем речь? Необходимо читать данные из стандартного потока ввода stdin и конвертировать в int/float или что-то еще.

В C это делается c помощью стандартной функции scanf() .

На Python обычно я делаю так:

import sys

for line in sys.stdin:
    a,b = map(int, line.split())

Проблема этого кода в том, что мы очень много раз вызываем функцию int.

Далее я нашел похожий вопрос/ответ на SO: https://stackoverflow.com/questions/12784192/is-there-a-faster-way-to-get-input-in-python. В том же ответе на SO я нашел интересный трюк, который сильно ускоряет работу с цифрами, при условии, что мы работаем c ascii от 0 до 9.

Итак вместо того, чтобы вызывать функцию int, давайте попробуем вызывать более быструю функцию ord со сдвигом 48, что позволит нам найти искомое число из строки.

import sys

for line in sys.stdin:
    x,y = [ord(x)-48 for x in line.split()]

Короткий бенчмарк:

import timeit

timeit.timeit('ord("1")-48')
# 0.0593524890136905

timeit.timeit('int("1")')
# 0.17183380699134432

=)