Làm cách nào để sao chép một chuỗi Python?


92

Tôi làm việc này:

a = 'hello'

Và bây giờ tôi chỉ muốn một bản sao độc lập của a:

import copy

b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)

map( id, [ a,b,c,d,e ] )

Hết [3]:

[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]

Tại sao tất cả chúng đều có cùng địa chỉ bộ nhớ và làm cách nào để tôi có được bản sao của bộ nhớ a?


3
Để nhận được câu trả lời khác với câu trả lời của Martijin (hoàn toàn chính xác, mặc dù không nhất thiết phải trả lời câu hỏi như đã nêu), bạn có thể muốn cung cấp thêm chi tiết / trường hợp sử dụng để cho biết lý do tại sao bạn muốn nó được sao chép.
elmo

4
Như @elemo ngụ ý, đây có thể là vấn đề XY .
martineau

2
Tôi quan tâm đến việc ước tính mức sử dụng bộ nhớ của một từ điển lồng nhau của biểu mẫu d[ 'hello' ] = e, ở đâu e[ 'hi' ] = 'again'. Để tạo một từ điển lồng nhau như vậy, tôi đã tạo một etừ điển duy nhất và sao chép nó nhiều lần. Tôi nhận thấy rằng mức tiêu thụ bộ nhớ rất thấp, dẫn đến câu hỏi của tôi ở đây. Bây giờ tôi hiểu rằng không có bản sao chuỗi nào được tạo, do đó tiêu thụ bộ nhớ thấp.
thường lệ tôi

1
Nếu bạn muốn blà một phiên bản sửa đổi của amà không cần sửa đổi a, chỉ cần cho blà kết quả của bất kỳ hoạt động nào. ví dụ: b = a[2:-1]đặt bthành 'll'acòn lại ' hello'.
OJFord

Ollie là chính xác. Điều này là do str là một kiểu bất biến. Do việc sử dụng các singleton của python (và có thể là các tối ưu hóa nội bộ khác), Bạn sẽ không thấy bộ nhớ mở rộng như mong đợi khi sao chép từ điển điện tử.
FizxMike

Câu trả lời:


137

Bạn không cần phải sao chép một chuỗi Python. Chúng là bất biến và copymô-đun luôn trả về bản gốc trong những trường hợp như vậy, cũng như vậy str(), toàn bộ lát chuỗi và nối với một chuỗi trống.

Hơn nữa, 'hello'chuỗi của bạn được thực hiện ( một số chuỗi nhất định ). Python cố tình chỉ giữ một bản sao, vì điều đó giúp tra cứu từ điển nhanh hơn.

Một cách bạn có thể giải quyết vấn đề này là thực sự tạo một chuỗi mới, sau đó cắt chuỗi đó trở lại nội dung ban đầu:

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

Nhưng tất cả những gì bạn đang làm là lãng phí bộ nhớ. Rốt cuộc, không phải là bạn có thể thay đổi các đối tượng chuỗi này theo bất kỳ cách nào.

Nếu tất cả những gì bạn muốn biết là một đối tượng Python yêu cầu bao nhiêu bộ nhớ, hãy sử dụng sys.getsizeof(); nó cung cấp cho bạn dấu chân bộ nhớ của bất kỳ đối tượng Python nào.

Đối với các thùng chứa, điều này không bao gồm nội dung; bạn phải đệ quy vào từng vùng chứa để tính tổng kích thước bộ nhớ:

>>> 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

Sau đó, bạn có thể chọn sử dụng id()theo dõi để lấy dung lượng bộ nhớ thực tế hoặc ước tính dung lượng bộ nhớ tối đa nếu các đối tượng không được lưu vào bộ nhớ đệm và sử dụng lại.


4
Có nhiều cách duy nhất để tạo một đối tượng chuỗi mới, chẳng hạn như b = ''.join(a).
martineau

@martineau: chắc chắn, tôi thực sự muốn nói 'một cách'.
Martijn Pieters

10
Nhấn mạnh vào "Bạn không cần sao chép một chuỗi Python". Có một lý do tại sao các hoạt động đó chỉ trả về cùng một chuỗi.
tcooc

1
Tuy nhiên, trong trường hợp này, OP đang cố gắng lãng phí bộ nhớ. Vì anh ta muốn biết bao nhiêu bộ nhớ sẽ được sử dụng bởi một số lượng chuỗi nhất định, đó là mục tiêu thực tế. Rõ ràng là anh ta có thể tạo ra các chuỗi duy nhất, nhưng đó chỉ là công việc không cần thiết như một giải pháp thay thế.
Gabe

8
+1 cho "tình cờ" bằng cách sử dụng một ví dụ sẽ xuất ra 42 .
Bakuriu

11

Bạn có thể sao chép một chuỗi trong python thông qua định dạng chuỗi:

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

4
Không đúng trong Python 3.6.5. id (a) và id (b) giống hệt nhau. Kết quả là không có thậm chí khác nhau khi tôi sử dụng phiên bản hiện đại của định dạng, tức là,.b = '{:s}'.format(a)
Seshadri R

7

Tôi chỉ bắt đầu một số thao tác chuỗi và tìm thấy câu hỏi này. Tôi có lẽ đang cố gắng làm một cái gì đó giống như OP, "tôi bình thường". Những câu trả lời trước đây không làm rõ ràng sự bối rối của tôi, nhưng sau khi suy nghĩ một chút về nó, cuối cùng tôi đã "hiểu được".

Chừng nào a, b, c, d, và ecó giá trị như nhau, họ tham khảo để cùng một chỗ. Bộ nhớ được lưu. Ngay sau khi biến bắt đầu có các giá trị khác nhau, chúng bắt đầu có các tham chiếu khác nhau. Kinh nghiệm học tập của tôi đến từ mã này:

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

Đầu ra được in là:

[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]

hello hello hello hello hello

[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]

goodbye hello hello hello hello something

Thông tin chi tiết cho hành vi được mô tả trong bài viết này stackoverflow.com/questions/2123925/...
dlasalle

3

Việc sao chép một chuỗi có thể được thực hiện theo hai cách hoặc sao chép vị trí a = "a" b = a hoặc bạn có thể sao chép, điều đó có nghĩa là b sẽ không bị ảnh hưởng khi a bị thay đổi, điều này được thực hiện bởi a = 'a' b = a [:]


2

Nói một cách khác "id ()" không phải là thứ bạn quan tâm. Bạn muốn biết liệu tên biến có thể được sửa đổi mà không gây hại cho tên biến nguồn hay không.

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

Nếu bạn đã quen với C, thì chúng giống như các biến con trỏ ngoại trừ bạn không thể hủy tham chiếu chúng để sửa đổi những gì chúng trỏ đến, nhưng id () sẽ cho bạn biết chúng hiện đang trỏ đến đâu.

Vấn đề đối với các lập trình viên python xảy ra khi bạn xem xét các cấu trúc sâu hơn như danh sách hoặc phân đoạn:

>>> o={'a': 10}                                                                                                                                                                                                                                                                                        
>>> x=o                                                                                                                                                                                                                                                                                                
>>> y=o.copy()                                                                                                                                                                                                                                                                                         
>>> x['a'] = 20                                                                                                                                                                                                                                                                                        
>>> y['a'] = 30                                                                                                                                                                                                                                                                                        
>>> o                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> x                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> y                                                                                                                                                                                                                                                                                                  
{'a': 30}                                                                                                                                                                                                                                                                                              

Ở đây o và x đề cập đến cùng một dict o ['a'] và x ['a'], và dict đó là "có thể thay đổi" theo nghĩa là bạn có thể thay đổi giá trị cho khóa 'a'. Đó là lý do tại sao "y" cần phải là một bản sao và y ['a'] có thể tham chiếu đến một thứ khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.