2010-05-25 76 views
29

Các id() chức năng sẵn có cho ...Sự khác biệt giữa "a là b" và "id (a) == id (b)" trong Python là gì?

một số nguyên (hoặc số nguyên dài) mà được đảm bảo là duy nhất và liên tục cho đối tượng này trong suốt cuộc đời của nó.

Nhà điều hành is, thay vào đó, mang đến cho ...

nhận dạng đối tượng

Vậy tại sao là nó có thể có hai đối tượng có cùng id nhưng trở False một is kiểm tra? Dưới đây là một ví dụ:

>>> class Test(): 
... def test(): 
...  pass 
>>> a = Test() 
>>> b = Test() 
>>> id(a.test) == id(b.test) 
True 
>>> a.test is b.test 
False 

Một ví dụ đáng lo ngại hơn: (tiếp tục ở trên)

>>> b = a 
>>> b is a 
True 
>>> b.test is a.test 
False 
>>> a.test is a.test 
False 

Tuy nhiên:

>>> new_improved_test_method = lambda: None 
>>> a.test = new_improved_test_method 
>>> a.test is a.test 
True 
+0

Nó không giống như tôi _need_ này cho một chương trình thực tế hoặc metaclass jedi tâm lừa, tâm trí bạn. Tôi đã chán trên tàu và tôi đã thử rằng :) – badp

+0

Tôi nghĩ rằng câu hỏi quan trọng là lý do tại sao 'a.test là a.test' là Sai. Một khi bạn biết rằng phần còn lại sẽ có ý nghĩa ... – Skilldrick

+0

Tràn dầu là tốt và dandy và nó đang đến một thành phố gần bạn thật sớm!Có lẽ bạn nên tổ chức một số có được với nhau để ăn mừng sắp tới của nó! – badp

Trả lời

51
>>> b.test is a.test 
False 
>>> a.test is a.test 
False 

Phương pháp được tạo ra on-the-fly mỗi thời gian bạn nhìn chúng. Đối tượng hàm (luôn là cùng một đối tượng) thực hiện các descriptor protocol__get__ của nó tạo đối tượng phương thức bị ràng buộc. Không có hai phương pháp ràng buộc bình thường sẽ là cùng một đối tượng.

>>> id(a.test) == id(b.test) 
True 
>>> a.test is b.test 
False 

Ví dụ này là lừa đảo. Kết quả của việc đầu tiên chỉ là True do trùng hợp ngẫu nhiên. a.test tạo ra một phương pháp bị ràng buộc và rác của nó được thu thập sau khi tính toán id(a.test) vì không có bất kỳ tham chiếu nào đến nó. (Lưu ý rằng bạn trích dẫn tài liệu nói rằng một id là "duy nhất và không đổi cho đối tượng này trong suốt đời của nó" (nhấn mạnh mỏ).) b.testxảy ra để có cùng id như phương pháp ràng buộc bạn có trước đây và nó được cho phép bởi vì không có đối tượng nào khác có cùng một id bây giờ.

Lưu ý rằng bạn hiếm khi sử dụng is và thậm chí ít thường xuyên sử dụng id. id(foo) == id(bar) luôn sai.


Về ví dụ mới của bạn, hy vọng bạn sẽ có được những gì nó làm bây giờ:

>>> new_improved_test_method = lambda: None 
>>> a.test = new_improved_test_method 
>>> a.test is a.test 
True 

Trong trường hợp này, chúng ta không làm cho các phương pháp một cách nhanh chóng từ chức năng trên lớp tự động ràng buộc bản thân và trở về đối tượng phương thức bị ràng buộc. Trong trường hợp này, bạn chỉ cần lưu trữ một hàm như một thuộc tính instance. Không có gì đặc biệt xảy ra khi tra cứu (chỉ các descriptor được gọi khi bạn tra cứu thuộc tính lớp), vì vậy mỗi khi bạn tra cứu thuộc tính, bạn sẽ nhận được đối tượng gốc mà bạn đã lưu trữ.

+3

Rất tốt! .. ... – Skilldrick

+7

* "Các phương thức được tạo khi đang di chuyển mỗi khi bạn nhìn chúng. Đối tượng hàm (luôn là cùng một đối tượng) thực hiện giao thức mô tả và' __get__' tạo đối tượng phương thức liên kết. các phương pháp thông thường sẽ là cùng một đối tượng. "* Ha, đó là tin cho tôi. Tốt đẹp! –

+1

Wow, rất khai sáng, cảm ơn! – PaulMcG

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