Bạn nên biết rằng các xét nghiệm sử dụng is
hoặc id
thể gây hiểu nhầm cho dù một bản sao y đang được thực hiện với bất biến và interned các đối tượng như chuỗi, số nguyên và bộ dữ liệu có chứa bất biến.
Hãy xem xét một dễ hiểu ví dụ về chuỗi thực tập nội trú:
>>> l1=['one']
>>> l2=['one']
>>> l1 is l2
False
>>> l1[0] is l2[0]
True
Bây giờ tạo một bản sao cạn của l1
và kiểm tra chuỗi bất biến:
>>> l3=l1[:]
>>> l3 is l1
False
>>> l3[0] is l1[0]
True
Bây giờ tạo một bản sao của chuỗi chứa bởi l1[0]
:
>>> s1=l1[0][:]
>>> s1
'one'
>>> s1 is l1[0] is l2[0] is l3[0]
True # they are all the same object
T ry một deepcopy nơi mọi yếu tố cần được sao chép:
>>> from copy import deepcopy
>>> l4=deepcopy(l1)
>>> l4[0] is l1[0]
True
Trong mỗi trường hợp, chuỗi 'one'
đang được thực tập nội trú vào bộ nhớ cache nội bộ Python của chuỗi bất biến và is
sẽ cho thấy rằng họ đều giống nhau (họ có cùng id
) . Nó được thực hiện và phụ thuộc phiên bản của những gì được interned và khi nào, vì vậy bạn không thể phụ thuộc vào nó. Nó có thể là một bộ nhớ đáng kể và nâng cao hiệu suất.
Bạn có thể buộc một ví dụ mà không được thực tập nội trú ngay lập tức:
>>> s2=''.join(c for c in 'one')
>>> s2==l1[0]
True
>>> s2 is l1[0]
False
Và sau đó bạn có thể sử dụng Python intern function gây rằng chuỗi để tham khảo các đối tượng lưu trữ nếu tìm thấy:
>>> l1[0] is s2
False
>>> s2=intern(s2)
>>> l1[0] is s2
True
Tương tự áp dụng cho các bộ dữ liệu không thay đổi:
>>> t1=('one','two')
>>> t2=t1[:]
>>> t1 is t2
True
>>> t3=deepcopy(t1)
>>> t3 is t2 is t1
True
An d danh sách có thể thay đổi các immutables (như số nguyên) có thể có các thành viên danh sách mai táng:
>>> li1=[1,2,3]
>>> li2=deepcopy(li1)
>>> li2 == li1
True
>>> li2 is li1
False
>>> li1[0] is li2[0]
True
Vì vậy, bạn có thể sử dụng các hoạt động python mà bạn biết sẽ sao chép một cái gì đó nhưng kết quả cuối cùng là một tham chiếu đến một đối tượng bất biến thực tập nội trú. Bài kiểm tra is
chỉ là một bài kiểm tra có tính dispositive của một bản sao được thực hiện NẾU các mục có thể thay đổi được.
Sau đó, tại sao tôi nhận được các id khác nhau – user2528042
@ user2528042: Bởi vì * đối tượng danh sách bên ngoài * không giống nhau. –
@ user2528042 Vì danh sách gốc * được sao chép * vào một đối tượng mới. Tất cả các phần tử bên trong không được sao chép, vì vậy nếu danh sách chứa một đối tượng có thể thay đổi (ints không thể thay đổi được), thì đối tượng sẽ thay đổi nó trong cả bản gốc và danh sách sao chép vì cả hai đều có một bản sao tham chiếu đến cùng một đối tượng. – poke