2016-02-03 18 views
5

Tôi đã quan sát thấy ít nhất 3 loại liên quan đến chức năng trong Python 3:Sự khác biệt giữa 'hàm', 'phương thức' và 'phương thức ràng buộc' trong Python 3 là gì?

>>> class A(): 
... def f(): pass 
... 
>>> A.f 
<function A.f at 0x7fcaef304268> 
>>> A().f 
<bound method A.f of <__main__.A object at 0x7fcaef2fae80 
>>> set.union 
<method 'union' of 'set' objects> 

Tôi đang tự hỏi sự khác biệt giữa 'chức năng', 'phương pháp' và 'phương pháp ràng buộc' là gì? 'Phương thức' có phải là một loại tương đương với 'phương pháp không liên kết' trong Python 2 không?

Trả lời

5

'Phương pháp' có phải là loại tương đương với 'phương pháp không liên kết' trong Python 2 không?

Kind-a-sort-a. Nhưng không thực sự. Nó là một đối tượng method_descriptor được định nghĩa trong mã C. Nó là một phương pháp không liên kết, nhưng không phải là loại bạn tìm thấy trong Python 2.

Đối với các loại Python được viết C, tất cả các 'phương thức' đều thực sự là hàm C. Đối tượng <method 'name' of 'type' objects> bạn tìm thấy là một đối tượng đặc biệt mà bạn có thể sử dụng để gọi hàm đó cho một cá thể và các đối số khác, giống như đối tượng function làm cho các lớp Python tùy chỉnh. Đối tượng được xác định trong C trong PyMethodDescr_Type structure. Nó thực hiện các descriptor protocol, giống như chức năng làm.

Python định nghĩa một số loại mô tả khác như vậy; nếu bạn sử dụng __slots__, mỗi thuộc tính là một dsescriptor loại member_descriptor (xem PyMemberDescr_Type structure), trong khi classmethod, propertystaticmethod có lẽ là các đối tượng mô tả được biết đến tốt hơn.

Trong Python 2, phương pháp ràng buộc và không ràng buộc thực sự chỉ là một loại, instancemethod (được xác định bởi PyMethod_Type structure); nó sẽ báo cáo là bị ràng buộc nếu thuộc tính __self__ (im_self) được đặt. Trong Python 3, sử dụng một hàm như một bộ mô tả đơn giản là không tạo ra các đối tượng phương thức mà không có tập hợp __self__; thay vào đó, hãy gọi function.__get__() mà không có cá thể nào chỉ trả lại hàm.

Lý do duy nhất Python 2 trả về các phương pháp không liên kết là thực thi kiểm tra loại; đối số đầu tiên phải là một thể hiện của lớp (hoặc một lớp con của nó). Điều này đã không làm cho tất cả những ý nghĩa nhiều cho mã Python hỗ trợ gõ vịt, vì vậy trong Python 3 hạn chế đã được gỡ bỏ. Tuy nhiên, với mã C bạn không thể sử dụng kiểu gõ vịt, bạn vẫn phải hạn chế loại, và đó là lý do tại sao C-type vẫn trả lại đối tượng method_descriptor thực thi hạn chế này.

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