2014-06-23 16 views
47

Tại sao kết quả đầu tiên là False, nó không phải là True?Hành vi rất lạ của toán tử 'là' với các phương pháp

>>> from collections import OrderedDict 
>>> OrderedDict.__repr__ is OrderedDict.__repr__ 
False 
>>> dict.__repr__ is dict.__repr__ 
True 
+1

Python 3.3 trả về True – HashSplat

+0

Đây là Python 2.7. – Chameleon

+1

@JustinEngel: Đó là vì Python 3 không sử dụng các phương thức không liên kết, tất cả các phương thức đều bị ràng buộc. Hãy thử 'OrderedDict() .__ repr__ là OrderedDict() .__ repr__' trong Python 3 và bạn sẽ thấy cùng một hành vi. –

Trả lời

56

Đối với hàm do người dùng định nghĩa, bằng Python 2 cởiràng buộc phương pháp được tạo ra theo yêu cầu, qua descriptor protocol; OrderedDict.__repr__ là một đối tượng phương thức như vậy, vì hàm bọc được thực hiện dưới dạng pure-Python function.

Giao thức mô tả sẽ gọi __get__ method trên các đối tượng hỗ trợ nó, vì vậy __repr__.__get__() được gọi bất cứ khi nào bạn cố truy cập OrderedDict.__repr__; đối với các lớp None (không có trường hợp nào) và chính đối tượng lớp được truyền vào. Bởi vì bạn nhận được một đối tượng phương thức mới mỗi lần hàm __get__ được gọi, is không thành công. Nó không phải là đối tượng phương thức tương tự.

dict.__repr__ không phải là hàm Python tùy chỉnh mà là hàm C và phương thức mô tả __get__ mô tả essentially just returns self when accessed on the class. Truy cập vào các thuộc tính mang đến cho bạn cùng một đối tượng mỗi lần, vì vậy is công trình:

>>> dict.__repr__.__get__(None, dict) is dict.__repr__ # None means no instance 
True 

phương pháp có một thuộc tính __func__ tham khảo chức năng bao bọc, sử dụng để kiểm tra danh tính:

>>> OrderedDict.__repr__ 
<unbound method OrderedDict.__repr__> 
>>> OrderedDict.__repr__.__func__ 
<function __repr__ at 0x102c2f1b8> 
>>> OrderedDict.__repr__.__func__.__get__(None, OrderedDict) 
<unbound method OrderedDict.__repr__> 
>>> OrderedDict.__repr__.__func__ is OrderedDict.__repr__.__func__ 
True 

Python 3 không đi với các phương thức không bị ràng buộc, function.__get__(None, classobj) trả về chính đối tượng hàm (vì vậy nó hoạt động như dict.__repr__). Nhưng bạn sẽ thấy hành vi tương tự với phương pháp bị ràng buộc, phương thức được truy xuất từ ​​một phiên bản.

+1

Như một phép thử đơn giản để chứng minh điều này cho chính bạn, tạo một lớp với phương thức '' __repr__'' của nó là '' __repr__ = lambda: x'' và kiểm tra '' is'' sẽ thất bại. Trên thực tế, ghi đè '' __repr__'' nói chung sẽ khiến '' is'' thất bại. – aruisdante

+0

Và, trong trường hợp tổng quát, các phương thức không ràng buộc tinh khiết của các lớp NO-python so sánh với '' True'' bằng '' là''. – aruisdante

+0

@aruisdante: tốt, bạn có thể tạo (nhiều hơn một) tham chiếu đến đối tượng phương thức, và sau đó bạn vẫn có thể sử dụng 'is'. Nhưng việc lấy một phương thức từ một lớp cho bạn một đối tượng mới vì phương thức '__get__' của hàm tạo ra một đối tượng mới. –

1

Hai số OrderedDict.__repr__ không bị ràng buộc vào cùng một đối tượng. Nếu bạn thử:

OrderedDict.__repr__ == OrderedDict.__repr__ 

bạn sẽ thấy rằng chúng có cùng giá trị.

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