Một bản sao khác đã hỏi tại sao hai chuỗi bằng nhau thường không giống nhau, điều này thực sự không được trả lời ở đây:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
Vì vậy, tại sao chúng không cùng một chuỗi? Đặc biệt là với điều này:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
Hãy tạm dừng phần thứ hai một chút. Làm thế nào cái đầu tiên có thể đúng?
Trình thông dịch sẽ phải có một "interning table", một bảng ánh xạ các giá trị chuỗi với các đối tượng chuỗi, vì vậy mỗi khi bạn cố gắng tạo một chuỗi mới với nội dung 'abc'
, bạn sẽ nhận lại cùng một đối tượng. Wikipedia có một cuộc thảo luận chi tiết hơn về cách hoạt động của interning.
Và Python có một bảng xen kẽ chuỗi; bạn có thể thực hiện thủ công các chuỗi bằng sys.intern
phương pháp này.
Trên thực tế, Python được phép tự động thực hiện bất kỳ kiểu bất biến nào, nhưng không bắt buộc phải làm như vậy. Các cách triển khai khác nhau sẽ đan xen các giá trị khác nhau.
CPython (triển khai bạn đang sử dụng nếu bạn không biết mình đang sử dụng triển khai nào) tự động thực hiện các số nguyên nhỏ và một số đơn lẻ đặc biệt như False
, nhưng không phải chuỗi (hoặc số nguyên lớn, hoặc bộ giá trị nhỏ hoặc bất kỳ thứ gì khác). Bạn có thể thấy điều này khá dễ dàng:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
OK, nhưng tại sao đã z
và w
giống hệt nhau?
Đó không phải là trình thông dịch tự động thực hiện, đó là các giá trị gấp của trình biên dịch.
Nếu cùng một chuỗi thời gian biên dịch xuất hiện hai lần trong cùng một module (những gì chính xác phương tiện này rất khó để xác định-nó không phải là điều tương tự như một chữ chuỗi, vì r'abc'
, 'abc'
và 'a' 'b' 'c'
tất cả đều literals khác nhau nhưng cùng một chuỗi nhưng dễ hiểu trực quan), trình biên dịch sẽ chỉ tạo một thể hiện của chuỗi, với hai tham chiếu.
Trên thực tế, trình biên dịch còn có thể tiến xa hơn nữa: 'ab' + 'c'
có thể được chuyển đổi thành 'abc'
bởi trình tối ưu hóa, trong trường hợp đó, nó có thể được gấp lại cùng với một 'abc'
hằng số trong cùng một mô-đun.
Một lần nữa, đây là điều mà Python được phép nhưng không bắt buộc phải làm. Nhưng trong trường hợp này, CPython luôn gấp các dây nhỏ (và cũng có thể, ví dụ, các bộ nhỏ). (Mặc dù trình biên dịch theo câu lệnh của trình thông dịch tương tác không chạy tối ưu hóa tương tự như trình biên dịch mô-đun tại một thời điểm, vì vậy bạn sẽ không thấy chính xác các kết quả tương tác.)
Vì vậy, bạn nên làm gì về điều này với tư cách là một lập trình viên?
Cũng không có gì. Bạn hầu như không bao giờ có bất kỳ lý do gì để quan tâm xem hai giá trị bất biến có giống hệt nhau hay không. Nếu bạn muốn biết khi nào bạn có thể sử dụng a is b
thay thế a == b
, bạn đang đặt câu hỏi sai. Chỉ luôn sử dụng a == b
ngoại trừ trong hai trường hợp:
- Đối với các so sánh dễ đọc hơn với các giá trị singleton như
x is None
.
- Đối với các giá trị có thể thay đổi, khi bạn cần biết liệu đột biến
x
sẽ ảnh hưởng đến y
.