Python Không có so sánh: tôi nên sử dụng dịch vụ là is hay hay ==?


212

Biên tập viên của tôi cảnh báo tôi khi tôi so sánh my_var == None, nhưng không có cảnh báo khi tôi sử dụng my_var is None.

Tôi đã thực hiện một thử nghiệm trong trình bao Python và xác định cả hai đều là cú pháp hợp lệ, nhưng trình soạn thảo của tôi dường như đang nói rằng nó my_var is Noneđược ưa thích hơn.

Đây có phải là trường hợp, và nếu vậy, tại sao?


7
PEP 8 nói ở đâu đó rằng bạn nên so sánh với các singletons bằng cách sử dụng is- python.org/dev/peps/pep-0008/#programming-recommendations
Biến động

2
Tấm áp phích đó đang nói về Python 3 và câu hỏi của tôi là về Python 2.x. Tôi không chắc đây có phải là một sự khác biệt đủ lớn để đảm bảo cả hai còn lại không nhưng tôi đã chỉnh sửa câu hỏi để đưa vào đó chỉ trong trường hợp.
Clay Wardell

2
Tôi không nghĩ câu hỏi này thực sự là một bản sao. Cái khác là về == vs nói chung, cái này là về Không nói riêng.
IJ Kennedy

Câu trả lời:


253

Tóm lược:

Sử dụng iskhi bạn muốn kiểm tra chống lại một đối tượng sắc (ví dụ như kiểm tra để xem nếu varNone). Sử dụng ==khi bạn muốn kiểm tra sựvar bằng nhau (ví dụ: Có bằng 3?).

Giải trình:

Bạn có thể có các lớp tùy chỉnh nơi my_var == Nonesẽ trở lạiTrue

ví dụ:

class Negator(object):
    def __eq__(self,other):
        return not other

thing = Negator()
print thing == None    #True
print thing is None    #False

iskiểm tra danh tính đối tượng . Chỉ có 1 đối tượng None, vì vậy khi bạn thực hiện my_var is None, bạn đang kiểm tra xem chúng có thực sự là cùng một đối tượng không (không chỉ các đối tượng tương đương )

Nói cách khác, ==là kiểm tra tính tương đương (được xác định từ đối tượng này sang đối tượng khác) trong khi iskiểm tra nhận dạng đối tượng:

lst = [1,2,3]
lst == lst[:]  # This is True since the lists are "equivalent"
lst is lst[:]  # This is False since they're actually different objects

22
Khi nào is Nonekhác với == None?
Máy xay sinh tố

11
@Blender Trong trường hợp được đề cập. __eq__có thể được định nghĩa theo bất kỳ cách nào, nhưng hành vi của iskhông thể thay đổi quá dễ dàng.
Lev Levitsky

5
@LevLevitsky: Một trong những ví dụ sử dụng Mython là "mở rộng các giao thức để bất kỳ toán tử nào cũng có thể bị quá tải, thậm chí is". Sau khi nhận xét về các danh sách, anh ấy đã đổi nó thành "Ngay cả is(nhưng chỉ khi bạn mất trí)."
abarnert

1
+1, nhưng sẽ tốt hơn nữa nếu câu trả lời này bao gồm tham chiếu PEP 8 mà những người khác làm (cũng như giải thích lý do tại sao quyết định đằng sau PEP 8 có ý nghĩa, điều này đã có).
abarnert

3
@abarnert - Tôi thậm chí còn không biết rằng PEP 8 đã đưa ra khuyến nghị ở đây. Vấn đề là họ là những nhà khai thác khác nhau làm những việc khác nhau. Có thể có trường hợp object == Nonethực sự thành ngữ chính xác (mặc dù tôi không thể nghĩ ra bất kỳ cái gì ngoài đỉnh đầu). Bạn chỉ cần biết những gì bạn đang làm.
mgilson

127

isthường được ưa thích khi so sánh các đối tượng tùy ý với các singletons Nonevì nó nhanh hơn và dễ dự đoán hơn. isluôn luôn so sánh theo danh tính đối tượng, trong khi những gì ==sẽ làm phụ thuộc vào loại toán hạng chính xác và thậm chí vào thứ tự của chúng.

Khuyến nghị này được hỗ trợ bởi PEP 8 , trong đó tuyên bố rõ ràng rằng "việc so sánh với những người độc thân như Không nên luôn luôn được thực hiện với ishoặc is not, không bao giờ là các nhà khai thác bình đẳng."


6
Cảm ơn bạn đã đăng bài này; câu trả lời được chấp nhận làm cho một số điểm thú vị, nhưng câu trả lời của bạn trực tiếp hơn nhiều.
Luke Davis

Có vẻ kỳ lạ khi dựa vào những gì thực chất là một chi tiết thực hiện. Tại sao tôi nên quan tâm có bao nhiêu trường hợp của noneType?
BallpointBen

@BallpointBen Bởi vì đó không phải là một chi tiết triển khai - chỉ có một Noneđối tượng theo hằng số toàn cầu None. Nếu bất cứ điều gì, NoneTypelà một chi tiết thực hiện bởi vì Nonesingleton phải có một số loại. (Việc bạn không thể tạo các thể hiện của loại này là một dấu hiệu tốt cho thấy một thể hiện của nó được dự định là một cá thể.)
user4815162342

@BallpointBen Tôi nghĩ điểm mấu chốt là Python sở hữu một khái niệm mạnh về nhận dạng đối tượng. Nếu bạn muốn kiểm tra xem một đối tượng có so sánh bằng hay không None, bằng mọi cách sử dụng obj == None. Nếu bạn muốn kiểm tra xem một đối tượng None , sử dụng obj is None. Quan điểm của khuyến nghị PEP 8 (và của câu trả lời này) là hầu hết mọi người đều muốn cái sau khi họ muốn kiểm tra Không, và nó cũng xảy ra nhanh hơn và rõ ràng hơn.
dùng4815162342

Nonecũng khác với các đối tượng được lưu trong bộ nhớ cache như 0và các số nguyên nhỏ khác, trong đó bộ đệm thực sự là một chi tiết triển khai. Sự khác biệt ở đây là một số nguyên có giá trị nội tại mang lại các thuộc tính của nó và nó có thể được tính toán. Mặt khác, Nonekhông có bất kỳ trạng thái nào, đó chỉ là bản sắc của nó quan trọng và làm cho nó trở nên đặc biệt.
dùng4815162342

11

PEP 8 định nghĩa rằng tốt hơn là sử dụng istoán tử khi so sánh singletons.

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.