파이썬 문자열을 어떻게 복사 할 수 있습니까?


92

나는 이것을한다:

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있습니까?


3
Martijin의 답변과 다른 답변을 얻으려면 (전적으로 정확하지만 반드시 명시된대로 질문에 답변하지는 않음) 더 자세한 정보 / 사용 사례를 제공 하여 복사하려는 이유 를 표시 할 수 있습니다.
elmo 2014-07-17

4
@elemo가 암시 하듯이 이것은 XY 문제 일 수 있습니다 .
martineau 2014-07-17

2
나는 형태의 중첩 된 사전의 메모리 사용량 추정에 관심이 d[ 'hello' ] = e곳을 e[ 'hi' ] = 'again'. 이러한 중첩 사전을 생성하기 위해 단일 e사전을 생성하고 여러 번 복사했습니다. 나는 메모리 소비가 매우 낮다는 것을 알았고 여기에 내 질문이 생겼습니다. 이제 문자열 복사본이 생성되지 않았으므로 메모리 소비가 적다는 것을 이해합니다.
평소 나

1
당신이 원하는 경우 b의 수정 된 버전으로 a수정하지 않고 a그냥 .. b어떤 작업의 결과. 예 b = a[2:-1]세트 b'll'a유적 ' hello'.
OJFord

Ollie가 맞습니다. 이것은 str이 불변 유형이기 때문입니다. 파이썬의 싱글 톤 (및 아마도 다른 내부 최적화) 사용으로 인해 e 사전을 복사 할 때 예상대로 메모리가 확장되는 것을 볼 수 없습니다.
FizxMike

답변:


137

Python 문자열을 복사 할 필요 가 없습니다 . 그것들은 불변이며, copy모듈은 do str(), 전체 문자열 슬라이스 및 빈 문자열로 연결하는 경우와 같은 경우 항상 원본을 반환 합니다.

또한, 귀하의 'hello'문자열은 인턴됩니다 ( 특정 문자열은 ). 파이썬은 딕셔너리 조회 속도를 높이기 때문에 의도적으로 하나의 복사본 만 유지하려고합니다.

이 문제를 해결할 수있는 한 가지 방법은 실제로 새 문자열을 만든 다음 해당 문자열을 다시 원래 내용으로 분할하는 것입니다.

>>> a = 'hello'
>>> b = (a + '.')[:-1]
>>> id(a), id(b)
(4435312528, 4435312432)

하지만 지금하고있는 일은 기억을 낭비하는 것뿐입니다. 결국 이러한 문자열 객체를 어떤 식 으로든 변경할 수있는 것처럼 보이지는 않습니다.

알고 싶은 것이 파이썬 객체에 필요한 메모리 양뿐이라면 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()추적을 사용하여 실제 메모리 공간을 사용하거나 객체가 캐시 및 재사용되지 않은 경우 최대 공간을 추정 하도록 선택할 수 있습니다 .


4
.NET과 같은 새 문자열 객체를 만드는 방법은 여러 가지가 있습니다 b = ''.join(a).
martineau 2014

@martineau : 물론, 나는 정말로 '편도'라고 말하려고했다.
Martijn Pieters

10
"파이썬 문자열을 복사 할 필요가 없습니다"에 대한 강조. 이러한 작업이 단순히 동일한 문자열을 반환하는 이유가 있습니다.
tcooc

1
그러나이 경우 OP는 메모리를 낭비하려고합니다. 그는 특정 양의 문자열이 얼마나 많은 메모리를 사용할 것인지 알고 싶어하기 때문에 이것이 실제 목표입니다. 분명히 그는 고유 한 문자열을 생성 할 수 있지만 해결 방법으로 불필요한 작업 일뿐입니다.
Gabe

8
42를 출력하는 예제를 사용하여 "인과 적으로"에 +1합니다 .
Bakuriu

11

문자열 형식을 통해 파이썬에서 문자열을 복사 할 수 있습니다.

>>> a = 'foo'  
>>> b = '%s' % a  
>>> id(a), id(b)  
(140595444686784, 140595444726400)  

4
Python 3.6.5에서는 사실이 아닙니다. id (a)와 id (b)는 동일합니다. 나는 형식, 즉의 현대 버전을 사용할 때 결과는 다르지도 않습니다.b = '{:s}'.format(a)
Seshadri R

7

방금 문자열 조작을 시작 하고이 질문을 찾았습니다. 나는 아마도 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

동작에 대한 자세한 내용은이 게시물에 설명되어 있습니다. stackoverflow.com/questions/2123925/…
dlasalle

3

문자열 복사는 두 가지 방법으로 수행 할 수 있습니다. a = "a"b = a 위치를 복사하거나 a = 'a'b = a [:]에 의해 수행되는 a가 변경 될 때 b가 영향을받지 않음을 의미하는 복제 할 수 있습니다.


2

다르게 말하면 "id ()"는 당신이 신경 쓰는 것이 아닙니다. 소스 변수 이름을 손상시키지 않고 변수 이름을 수정할 수 있는지 알고 싶습니다.

>>> a = 'hello'                                                                                                                                                                                                                                                                                        
>>> b = a[:]                                                                                                                                                                                                                                                                                           
>>> c = a                                                                                                                                                                                                                                                                                              
>>> b += ' world'                                                                                                                                                                                                                                                                                      
>>> c += ', bye'                                                                                                                                                                                                                                                                                       
>>> a                                                                                                                                                                                                                                                                                                  
'hello'                                                                                                                                                                                                                                                                                                
>>> b                                                                                                                                                                                                                                                                                                  
'hello world'                                                                                                                                                                                                                                                                                          
>>> c                                                                                                                                                                                                                                                                                                  
'hello, bye'                                                                                                                                                                                                                                                                                           

C에 익숙하다면 포인터 변수와 비슷하지만 가리키는 내용을 수정하기 위해 역 참조 할 수는 없지만 id ()는 현재 가리키는 위치를 알려줍니다.

파이썬 프로그래머의 문제는 목록이나 사전과 같은 더 깊은 구조를 고려할 때 발생합니다.

>>> 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']는 다른 것을 참조 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.