Я делаю это:
a = 'hello'
А теперь мне просто нужна независимая копия a
:
import copy
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
map( id, [ a,b,c,d,e ] )
Из [3]:
[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]
Почему все они имеют одинаковый адрес памяти и как получить копию a
?
python
string
python-2.7
обычно я
источник
источник
d[ 'hello' ] = e
, гдеe[ 'hi' ] = 'again'
. Чтобы создать такой вложенный словарь, я создал одинe
словарь и скопировал его несколько раз. Я заметил, что потребление памяти было очень низким, что привело к моему вопросу здесь. Теперь я понимаю, что копий строк не создавалось, отсюда и низкое потребление памяти.b
быть модифицированной версиейa
без измененийa
, просто позвольтеb
быть результатом любой операции. например ,b = a[2:-1]
наборыb
для'll'
иa
остается "hello'
.Ответы:
Вам не нужно копировать строку Python. Они неизменяемы, и
copy
в таких случаях модуль всегда возвращает оригинал, как иstr()
весь фрагмент строки и конкатенацию с пустой строкой.Более того, ваша
'hello'
строка интернирована ( некоторые строки есть ). Python намеренно пытается сохранить только одну копию, так как это ускоряет поиск по словарю.Один из способов обойти это - создать новую строку, а затем нарезать ее обратно до исходного содержимого:
>>> a = 'hello' >>> b = (a + '.')[:-1] >>> id(a), id(b) (4435312528, 4435312432)
Но все, что вы делаете сейчас, это тратите память. В конце концов, вы не можете каким-либо образом изменить эти строковые объекты.
Если все, что вам нужно знать, это сколько памяти требуется объекту Python, используйте
sys.getsizeof()
; он дает вам объем памяти любого объекта Python.Для контейнеров это не включает содержимое; вам нужно будет пройти рекурсию в каждый контейнер, чтобы вычислить общий размер памяти:
>>> import sys >>> a = 'hello' >>> sys.getsizeof(a) 42 >>> b = {'foo': 'bar'} >>> sys.getsizeof(b) 280 >>> sys.getsizeof(b) + sum(sys.getsizeof(k) + sys.getsizeof(v) for k, v in b.items()) 360
Затем вы можете выбрать использование
id()
отслеживания для получения фактического объема памяти или для оценки максимального объема памяти, если объекты не были кэшированы и повторно использованы.источник
b = ''.join(a)
.Вы можете скопировать строку в Python с помощью форматирования строки:
>>> a = 'foo' >>> b = '%s' % a >>> id(a), id(b) (140595444686784, 140595444726400)
источник
b = '{:s}'.format(a)
Я только начинаю манипуляции со строками и нашел этот вопрос. Я, наверное, пытался сделать что-то вроде OP, «обычный я». Предыдущие ответы не прояснили мое замешательство, но, немного подумав, я, наконец, "понял".
До тех пор , как
a
,b
,c
,d
иe
имеют такое же значение, они ссылаются на то же место. Память сохранена. Как только переменные начинают иметь разные значения, они начинают иметь разные ссылки. Мой опыт обучения исходил из этого кода:import copy a = 'hello' b = str(a) c = a[:] d = a + '' e = copy.copy(a) print map( id, [ a,b,c,d,e ] ) print a, b, c, d, e e = a + 'something' a = 'goodbye' print map( id, [ a,b,c,d,e ] ) print a, b, c, d, e
Распечатанный результат:
[4538504992, 4538504992, 4538504992, 4538504992, 4538504992] hello hello hello hello hello [6113502048, 4538504992, 4538504992, 4538504992, 5570935808] goodbye hello hello hello hello something
источник
Копирование строки может быть выполнено двумя способами: либо скопировать местоположение a = "a" b = a, либо вы можете клонировать, что означает, что b не пострадает при изменении a, что выполняется a = 'a' b = a [:]
источник
Другими словами, id () - это не то, что вас волнует. Вы хотите знать, можно ли изменить имя переменной без ущерба для имени исходной переменной.
>>> a = 'hello' >>> b = a[:] >>> c = a >>> b += ' world' >>> c += ', bye' >>> a 'hello' >>> b 'hello world' >>> c 'hello, bye'
Если вы привыкли к C, то они похожи на переменные-указатели, за исключением того, что вы не можете отменить ссылку на них, чтобы изменить то, на что они указывают, но id () сообщит вам, где они в настоящее время указывают.
Проблема для программистов на Python возникает, когда вы рассматриваете более глубокие структуры, такие как списки или dicts:
>>> o={'a': 10} >>> x=o >>> y=o.copy() >>> x['a'] = 20 >>> y['a'] = 30 >>> o {'a': 20} >>> x {'a': 20} >>> y {'a': 30}
Здесь o и x относятся к одному и тому же dict o ['a'] и x ['a'], и этот dict является "изменяемым" в том смысле, что вы можете изменить значение для ключа 'a'. Вот почему «y» должно быть копией, а y ['a'] может относиться к чему-то еще.
источник