2013-05-23 17 views
6

Tôi đã cố gắng tìm kiếm một số thứ về nó. Tại sao các mô tả phi dữ liệu hoạt động với các lớp kiểu cũ?Mô tả Python với các lớp học kiểu cũ

Tài liệu nói rằng chúng không được:
"Note that descriptors are only invoked for new style objects or classes (ones that subclass object() or type()).".

class Descriptor(object): 
    def __init__(self): 
     self.x = 1 

    def __get__(self, obj, cls=None): 
     return self.x 


class A: 
    x = Descriptor() 

a = A() 
a.x 

>>> 1 

Cảm ơn.

+0

Vì 'Trình mô tả' là một lớp kiểu mới. – martineau

Trả lời

4

Bạn có quyền đặt câu hỏi về tài liệu. Tôi đã thử tìm kiếm thông qua CPython sources để tìm giải thích, nhưng được cảnh báo: Tôi không có chuyên gia.

Từ hiểu biết của tôi, thuộc tính tra cứu và mô tả __get__ gọi xảy ra trong instance_getattr2 (chiết xuất chọn):

v = class_lookup(inst->in_class, name, &klass); 
if (v != NULL) { 
    f = TP_DESCR_GET(v->ob_type); 
    if (f != NULL) { 
     PyObject *w = f(v, (PyObject *)inst, (PyObject *)(inst->in_class)); 
    } 
} 

Vì vậy, hoặc là tôi đang thiếu cái gì, hoặc không có gì trong việc thực hiện đòi hỏi một đối tượng kiểu mới (điều này mâu thuẫn tài liệu).

Đối với bản ghi, tôi đã thử biên dịch lại Python để hạn chế lời gọi mô tả đối với các đối tượng lớp kiểu mới, nhưng nó thực sự đã tạo ra một mớ hỗn độn khổng lồ. Tôi đã học được trong quá trình rằng các phương thức lớp được thực hiện như là các bộ mô tả: đây là cơ chế được sử dụng để trả về các đối tượng phương thức bị ràng buộc hoặc không liên kết tùy thuộc vào cách sử dụng. Ví dụ:

>>> class A: 
...  def foo(): 
...   pass 
... 
>>> A.foo.__get__(None, A) 
<unbound method A.foo> 
>>> A.foo.__get__(A(), A) 
<bound method A.foo of <__main__.A instance at 0x000000000229CC48>> 

Kết quả là, dường như ngăn ngừa mô tả gọi cho các thuộc tính của các đối tượng kiểu cũ hoặc các lớp học cũng sẽ ngăn chặn phương pháp kêu gọi họ, ít nhất là với thực hiện CPython.

Một lần nữa, tôi không có chuyên gia và đây là lần đầu tiên tôi đi sâu vào việc triển khai Python, vì vậy tôi có thể rất sai. Tôi đã nộp an issue để cố gắng làm rõ điều này.

+0

Cảm ơn bạn đã điều tra, nó thực sự hữu ích. – alexvassel

+0

Tôi đã chỉnh sửa câu trả lời của mình sau một phiên gỡ lỗi trong CPython: Tôi đã có các hàm sai liên quan, nhưng kết quả vẫn giữ nguyên. – icecrime

+0

Công việc tuyệt vời, cảm ơn lần nữa) – alexvassel