2010-09-05 37 views
10

Tôi nhận thấy tôi có thể sử dụng toán tử == để so sánh tất cả các kiểu dữ liệu gốc (số nguyên, chuỗi, booleans, số dấu chấm động vv) và danh sách, bộ, bộ và từ điển có chứa kiểu dữ liệu gốc. Trong những trường hợp này, toán tử == kiểm tra xem hai đối tượng có bằng nhau hay không. Nhưng trong một số trường hợp khác (cố gắng để so sánh trường hợp lớp học mà tôi tạo ra) các nhà điều hành == chỉ kiểm tra nếu hai biến tham chiếu đến cùng một đối tượng (như vậy trong những trường hợp này các nhà điều hành == là tương đương với các nhà điều hành is)Khi nào toán tử `==` không tương đương với toán tử `is`? (Python)

Câu hỏi của tôi là: Khi nào nhà điều hành == làm nhiều việc hơn là chỉ so sánh danh tính?

EDIT: Tôi đang sử dụng Python 3

+1

Về cơ bản, '==' là khác nhau từ 'is', bất cứ khi nào một lớp đè 'phương pháp __eq__' nó được thừa hưởng từ' object', vì vậy không có câu trả lời dễ câu hỏi này. Tùy thuộc vào phiên bản Python bạn đang sử dụng, mọi thứ trở nên phức tạp hơn do sự tồn tại của '__cmp__'. Bên cạnh sự tò mò, có lý do thực tế nào cho câu hỏi không? – Dirk

+0

@Dirk, cảm ơn. Tôi yêu cầu nó chủ yếu là do tò mò, nhưng tôi cũng nghĩ rằng nó là tốt để biết khi nào chính xác tôi có thể sử dụng toán tử == để kiểm tra bình đẳng đối tượng. – snakile

Trả lời

19

Trong Python, các nhà điều hành == được thực hiện trong điều khoản của magic method __eq__, mà theo mặc định thực hiện nó bằng cách so sánh bản sắc. Tuy nhiên, bạn có thể ghi đè phương thức để cung cấp khái niệm về sự bình đẳng đối tượng của riêng bạn. Lưu ý, nếu bạn làm như vậy, bạn thường cũng sẽ ghi đè ít nhất __ne__ (thực hiện toán tử !=) và __hash__, tính toán mã băm cho cá thể.

tôi thấy nó rất hữu ích, thậm chí bằng Python, để làm cho __eq__ hiện thực của tôi tuân thủ các quy tắc đề ra trong ngôn ngữ Java cho việc triển khai các phương pháp equals, cụ thể là:

  • Đó là phản xạ: đối với bất kỳ giá trị tham chiếu không null x, x.equals (x) phải trả về giá trị true.
  • Đối xứng là: đối với bất kỳ giá trị tham chiếu không null nào x và y, x.equals (y) sẽ trả về true nếu và chỉ khi y.equals (x) trả về giá trị true.
  • Chuyển tiếp: cho bất kỳ giá trị tham chiếu không null nào x, y và z, nếu x.equals (y) trả về true và y.equals (z) trả về true, thì x.equals (z) phải trả về true .
  • Điều này nhất quán: đối với bất kỳ giá trị tham chiếu không rỗng x và y, nhiều lần gọi x.equals (y) luôn trả về true hoặc return false false, miễn là không có thông tin nào được sử dụng bằng so sánh trên các đối tượng được sửa đổi.
  • Đối với bất kỳ giá trị tham chiếu không null nào x, x.equals (null) sẽ trả về false.

người cuối cùng có lẽ nên thay thế null bằng None, nhưng các quy tắc không dễ dàng như ở đây bằng Python như trong Java.

+0

Cảm ơn bạn đã đặt quy tắc để triển khai '__eq__' – snakile

+3

"Quy tắc" này có gốc toán học mạnh mẽ: http://en.wikipedia.org/wiki/Equivalence_relation –

+1

cho biết rằng javascript -> http://stackoverflow.com/questions/1995113/strangest-language-feature/1998224 # 1998224 – wim

16

==is luôn khác biệt về mặt khái niệm: các đại biểu cũ cho đối tượng bên trái là __eq__ [1], sau này luôn kiểm tra danh tính mà không có bất kỳ ủy quyền nào. Điều có vẻ khiến bạn khó hiểu là object.__eq__ (được thừa kế theo mặc định bởi các lớp do người dùng mã hóa không ghi đè lên nó), tất nhiên!) Được thực hiện dưới dạng nhận dạng (sau khi tất cả, một số object là hoàn toàn không có gì kiểm tra ngoại trừ danh tính của nó, vì vậy có thể làm gì khác?! -).

[1] bỏ qua để đơn giản khái niệm cũ của phương pháp __cmp__, đây chỉ là biến chứng biên và thay đổi không có gì quan trọng trong gist của đoạn ;-).

4

gì là có lẽ quan trọng nhất Vấn đề là giới thiệu đó là luôn luôn sử dụng:

if myvalue is None: 
không

if myvalue == None: 

Và không bao giờ sử dụng:

if myvalue is True: 

nhưng việc sử dụng:

if myvalue: 

Điểm sau này không quá rõ ràng với tôi vì tôi nghĩ có lần để tách biệt giá trị True từ các giá trị True khác như "Alex Martelli", nói không có Sai trong "Alex Martelli" (tuyệt đối không, thậm chí là đưa ra ngoại lệ :)) nhưng có '' trong "Alex Martelli" (như trong bất kỳ chuỗi nào khác).

+0

Điều gì khiến 'if myvalue is None' tốt hơn 'if myvalue == None'? – snakile

+3

Xem PEP8 để biết quy tắc. Xem nhận xét của Alex về __eq__, bổ sung nó nhanh hơn: http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html –

7

== làm nhiều hơn so sánh danh tính khi có liên quan. Nó không chỉ kiểm tra xem hai int là cùng một đối tượng hay không; nó thực sự đảm bảo giá trị của chúng phù hợp. Hãy xem xét:

>>> x=10000 
>>> y=10000 
>>> x==y,x is y 
(True, False) 
>>> del x 
>>> del y 
>>> x=10000 
>>> y=x 
>>> x==y,x is y 
(True, True) 

Triển khai Python "chuẩn" thực hiện một số nội dung đằng sau hậu trường cho nhỏ, vì vậy khi thử nghiệm với các giá trị nhỏ, bạn có thể nhận được điều gì đó khác. Hãy so sánh này cho 10000 trường hợp tương đương:

>>> del y 
>>> del x 
>>> x=1 
>>> y=1 
>>> x==y,x is y 
(True, True) 
+2

thú vị. +1 – snakile

Các vấn đề liên quan