Trong một bình luận về câu hỏi này , tôi đã thấy một tuyên bố được khuyến nghị sử dụng
result is not None
đấu với
result != None
Tôi đã tự hỏi sự khác biệt là gì, và tại sao người ta có thể được đề nghị hơn người khác?
Trong một bình luận về câu hỏi này , tôi đã thấy một tuyên bố được khuyến nghị sử dụng
result is not None
đấu với
result != None
Tôi đã tự hỏi sự khác biệt là gì, và tại sao người ta có thể được đề nghị hơn người khác?
Câu trả lời:
==
là một bài kiểm tra bình đẳng . Nó kiểm tra xem phía bên tay phải và phía bên trái có phải là các đối tượng bằng nhau hay không (theo phương pháp __eq__
hoặc __cmp__
phương pháp của họ .)
is
là một bài kiểm tra danh tính . Nó kiểm tra xem phía bên tay phải và phía bên trái có phải là cùng một đối tượng hay không. Không có phương thức nào được thực hiện, các đối tượng không thể ảnh hưởng đếnis
hoạt động.
Bạn sử dụng is
(và is not
) cho các singletons, như None
, nơi bạn không quan tâm đến các đối tượng có thể muốn giả vờ None
hoặc nơi bạn muốn bảo vệ chống lại các vật thể bị phá vỡ khi so sánh với None
.
None
có ít phương thức và hầu như không có thuộc tính. Nếu __eq__
thử nghiệm của bạn mong đợi một phương thức hoặc thuộc tính, nó có thể bị hỏng. def __eq__( self, other ): return self.size == other.size
. Ví dụ, sẽ phá vỡ nếu other
xảy ra None
.
is
giống như Java ==
. Python ==
giống như của Java .equals()
. Tất nhiên điều này chỉ có ích nếu bạn biết Java.
is
nó giống như ===
(rất bằng nhau) và ngược lại is not
là như thế !==
(không chính xác bằng nhau).
is not
một nhà điều hành duy nhất hoặc nó chỉ phủ nhận kết quả của is
nội bộ như thế not foo is bar
nào?
Đầu tiên, hãy để tôi đi qua một vài điều khoản. Nếu bạn chỉ muốn câu hỏi của mình được trả lời, hãy cuộn xuống "Trả lời câu hỏi của bạn".
Nhận dạng đối tượng : Khi bạn tạo một đối tượng, bạn có thể gán nó cho một biến. Sau đó bạn cũng có thể gán nó cho một biến khác. Và một cái khác.
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
Trong trường hợp này, cancel
, close
, và dismiss
tất cả các tham chiếu đến cùng một đối tượng trong bộ nhớ. Bạn chỉ tạo một Button
đối tượng và cả ba biến tham chiếu đến một đối tượng này. Chúng tôi nói rằng cancel
, close
và dismiss
tất cả đều đề cập đến các đối tượng giống hệt nhau ; nghĩa là, họ đề cập đến một đối tượng duy nhất.
Bình đẳng đối tượng : Khi bạn so sánh hai đối tượng, bạn thường không quan tâm mà nó đề cập đến chính xác cùng một đối tượng trong bộ nhớ. Với sự bình đẳng đối tượng, bạn có thể xác định quy tắc của riêng mình để so sánh hai đối tượng. Khi bạn viết if a == b:
, về cơ bản bạn đang nói if a.__eq__(b):
. Điều này cho phép bạn xác định một __eq__
phương thức trên a
để bạn có thể sử dụng logic so sánh của riêng bạn.
Đặt vấn đề: Hai đối tượng có cùng một dữ liệu, nhưng không giống nhau. (Chúng không phải là cùng một đối tượng trong bộ nhớ.) Ví dụ: String
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
Lưu ý: Tôi sử dụng các chuỗi unicode ở đây vì Python đủ thông minh để sử dụng lại các chuỗi thông thường mà không tạo các chuỗi mới trong bộ nhớ.
Ở đây, tôi có hai chuỗi unicode, a
và b
. Chúng có cùng một nội dung, nhưng chúng không phải là cùng một đối tượng trong bộ nhớ. Tuy nhiên, khi chúng ta so sánh chúng, chúng ta muốn chúng so sánh bằng nhau. Điều đang xảy ra ở đây là đối tượng unicode đã thực hiện __eq__
phương thức này.
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
Lưu ý: __eq__
trên unicode
chắc chắn được thực hiện hiệu quả hơn thế này.
Đặt vấn đề: Hai đối tượng có dữ liệu khác nhau, nhưng được coi là cùng một đối tượng nếu một số dữ liệu chính là như nhau. Ví dụ: Hầu hết các loại dữ liệu mô hình
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
Ở đây, tôi có hai màn hình Dell, a
và b
. Họ có cùng kiểu dáng và mẫu mã. Tuy nhiên, chúng không có cùng dữ liệu và cũng không phải là cùng một đối tượng trong bộ nhớ. Tuy nhiên, khi chúng ta so sánh chúng, chúng ta muốn chúng so sánh bằng nhau. Điều đang xảy ra ở đây là đối tượng Monitor đã thực hiện __eq__
phương thức này.
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
Khi so sánh với None
, luôn luôn sử dụngis not
. Không có gì là một singleton trong Python - chỉ có một phiên bản của nó trong bộ nhớ.
Bằng cách so sánh danh tính , điều này có thể được thực hiện rất nhanh. Python kiểm tra xem đối tượng bạn đang đề cập có cùng địa chỉ bộ nhớ với đối tượng Không toàn cầu hay không - so sánh hai số rất nhanh.
Bằng cách so sánh sự bằng nhau , Python phải tìm kiếm xem đối tượng của bạn có __eq__
phương thức hay không. Nếu không, nó sẽ kiểm tra từng siêu lớp tìm kiếm một __eq__
phương thức. Nếu nó tìm thấy một, Python gọi nó. Điều này đặc biệt tệ nếu __eq__
phương thức chậm và không quay lại ngay lập tức khi thông báo rằng đối tượng kia làNone
.
Bạn đã không thực hiện __eq__
? Sau đó, Python có thể sẽ tìm __eq__
phương thức trên object
và sử dụng phương thức đó thay vào đó - chỉ kiểm tra danh tính đối tượng.
Khi so sánh hầu hết những thứ khác trong Python, bạn sẽ sử dụng !=
.
Hãy xem xét những điều sau đây:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
None
là một singleton, do đó so sánh danh tính sẽ luôn hoạt động, trong khi một đối tượng có thể giả mạo so sánh bình đẳng thông qua .__eq__()
.
None
, nhưng hành vi không chính xác liên quan None
có thể xảy ra như là một tác dụng phụ của việc thực hiện bình đẳng chống lại các loại khác. Đó không phải là quá nhiều ý nghĩa bảo mật vì nó chỉ là ý nghĩa chính xác.
>>> () là () Thật >>> 1 là 1 Thật >>> (1,) == (1,) Thật >>> (1,) là (1,) Sai >>> a = (1,) >>> b = a >>> a là b Thật
Một số đối tượng là singletons, và do đó is
với chúng là tương đương với ==
. Hầu hết là không.
()
và 1
vốn không phải là singletons.
-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) và các bộ dữ liệu trống là các singletons. Quả thực nó không được ghi nhận cũng không được bảo đảm, nhưng nó không có khả năng thay đổi.