0
0
Lập trình
TT

Sự khác biệt giữa identity và equality trong Python

Đăng vào 6 ngày trước

• 5 phút đọc

"is" và "==": Nghệ thuật tinh tế của Identity và Equality trong Python

Khi học Python, bạn sẽ thường gặp những sự khác biệt tinh tế mà ban đầu có thể không rõ ràng. Một trong những khác biệt này là giữa is==. Nhìn qua, chúng đều có vẻ như trả lời cùng một câu hỏi: "Những thứ này có giống nhau không?" Nhưng thực tế, chúng trả lời hai câu hỏi khác nhau.

Hãy bắt đầu từ những điều cơ bản.

Phần 1: Hai Câu Hỏi

Python cho phép bạn hỏi:

  • Hai giá trị này có cùng nội dung không?

Bạn sử dụng == để hỏi câu này.

  • Hai giá trị này có tham chiếu đến cùng một đối tượng trong bộ nhớ không?

Bạn sử dụng is để hỏi câu này.

Nói một cách đơn giản:

  • == hỏi, "Chúng có trông giống nhau không?"

  • is hỏi, "Chúng có phải là một thực thể không?"

Hãy xem một vài ví dụ:

Copy
a = [1, 2, 3]
b = [1, 2, 3]

print(a == b) # True (cùng nội dung)
print(a is b) # False (các đối tượng khác nhau)

Ban đầu, điều này có thể cảm thấy lạ lùng. Nếu cả hai đều là [1, 2, 3], tại sao chúng lại không giống nhau?

Bởi vì Python đã tạo ra hai danh sách riêng biệt trong bộ nhớ. Chúng chứa cùng một giá trị, nhưng không phải là cùng một đối tượng. Giống như hai cuộn giấy có cùng nội dung, một cuộn được sao chép từ cuộn kia. Nếu bạn chỉnh sửa một cuộn, cuộn kia vẫn giữ nguyên.

Đây là trái tim của sự khác biệt giữa equality và identity.


Phần 2: Tại sao lại sử dụng is?

Tại sao không chỉ luôn luôn sử dụng ==?

Toán tử is không phải là về sự bình đẳng của nội dung, mà là về identity. Có những trường hợp mà identity rất quan trọng. Một trong số đó là kiểm tra một đối tượng sentinel, chẳng hạn như None.

Copy
if user_input is None:
    print("Không có dữ liệu đầu vào.")

Ở đây, bạn không hỏi "Dữ liệu đầu vào có giống như None không?", mà là "Dữ liệu đầu vào có phải là đối tượng None không?"

Sự phân biệt này đảm bảo sự rõ ràng và chính xác khi viết mã tương tác với các dấu hiệu hoặc đối tượng singleton.


Phần 3: Cạm bẫy tinh tế của các loại không thể thay đổi

Bây giờ hãy bước vào một khu vực khó hơn. Hành vi của các loại không thể thay đổi, chẳng hạn như số nguyên, chuỗi và tuple.

Hãy xem:

Copy
a = 1000
b = 1000

print(a == b) # True 
print(a is b) # False (trên hầu hết các hệ thống)

Nhưng sau đó:

Copy
x = 5
y = 5

print(x == y) # True 
print(x is y) # True

Tại sao lại có sự không nhất quán này?

Điều này là do một chi tiết thực hiện của CPython (trình biên dịch Python được sử dụng rộng rãi nhất). Để tối ưu hiệu suất, CPython lưu cache các số nguyên nhỏ và một số chuỗi. Vì vậy, các giá trị nhỏ có thể chỉ đến cùng một đối tượng. Nhưng đây không phải là điều bạn nên dựa vào. Đây chỉ là một đặc điểm, không phải là một bảo đảm.

Nói cách khác: sinh viên thấy rằng 1 is 1, và giả định điều tương tự với 1000 is 1000. Nhưng sự thật thay đổi một cách tinh tế với quy mô, giống như màn sương tan biến để lộ ra hai con đường thay vì một.


Phần 4: Các bộ chứa và Identity

Hãy đi sâu hơn một chút. Còn các bộ chứa rỗng thì sao?

Copy
print([] == []) # True - cùng nội dung (cả hai đều rỗng)
print([] is []) # False - các đối tượng danh sách khác nhau

Python tạo ra một danh sách mới mỗi khi bạn viết []. Chúng là riêng biệt, mặc dù có vẻ giống nhau. Giống như các cuộn giấy của sinh viên, hoàn toàn giống nhau về mặt từ ngữ, nhưng thay đổi một cuộn sẽ không ảnh hưởng đến cuộn khác.

Còn tuples thì sao?

Copy
print( () == () ) # True 
print( () is () ) # True (thường thì)

Ở đây, chúng ta gặp lại việc lưu cache của CPython. Bởi vì () là không thể thay đổi và phổ biến, Python có thể sử dụng lại cùng một đối tượng. Nhưng hành vi này không được quy định bởi đặc tả ngôn ngữ Python, đó là một chi tiết thực hiện.

Từ Python 3.8 trở đi, một số so sánh như () is () thậm chí còn gây ra SyntaxWarning, nhẹ nhàng nhắc nhở sinh viên xem xét lại giả định của họ.


Thực hành tốt nhất

  1. Sử dụng == khi so sánh giá trị.

Bạn đang hỏi, liệu hai điều này có cùng ý nghĩa hoặc nội dung không?

  1. Sử dụng is khi kiểm tra identity, đặc biệt là với các singleton như None, True, False, hoặc một đối tượng sentinel mà bạn định nghĩa.

  2. Tránh sử dụng is với các hằng số hoặc giá trị không thể thay đổi, trừ khi bạn có lý do cụ thể để quan tâm đến identity, và ngay cả khi đó, hãy ghi chú lý do đó.


Suy ngẫm Cuối cùng

Bài học của bậc thầy rất đơn giản:

Hai cuộn giấy có thể trông giống nhau. Nhưng khi bạn thay đổi một cuộn, sự thật về sự tách biệt của chúng sẽ được tiết lộ.

Trong Python, ==is dạy chúng ta nhìn sâu hơn bề mặt. Equality là về hình thức. Identity là về bản chất. Và hiểu sự khác biệt này không chỉ là một chi tiết kỹ thuật, mà còn là một thực hành trong việc nhìn nhận mọi thứ đúng như bản chất của chúng.

Cảm ơn bạn đã đọc Python Koans! Nếu bạn thấy bài viết này thú vị, hãy chia sẻ với bạn bè hoặc đăng ký bên dưới:

Python Koans | Vivis Dev | Substack

Các bài học Python được gói gọn trong những câu đố. Những câu đố nhỏ, những sự thật sâu sắc. Không phải là một chuỗi hướng dẫn thông thường. Nhấp để đọc Python Koans, bởi Vivis Dev, một xuất bản trên Substack với hàng trăm người đăng ký.

pythonkoans.substack.com

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào