2011-08-11 48 views
30

Tôi gặp phải hành vi này khi cố gắng để có được trang trí lớp và trang trí phương pháp để chơi độc đáo với nhau. Về cơ bản, các trình trang trí phương thức sẽ gắn cờ một số phương thức đặc biệt với một số giá trị giả, và trình trang trí lớp sẽ đến sau và điền vào giá trị sau này. Đây là một ví dụ đơn giảnThêm thuộc tính vào instancemethods bằng Python

>>> class cow: 
>>>  def moo(self): 
>>>   print 'mooo' 
>>>  moo.thing = 10 
>>> 
>>> cow.moo.thing 
10 
>>> cow().moo.thing 
10 
>>> cow.moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow().moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow.moo.__func__.thing = 5 
>>> cow.moo.thing 
5 

Có ai biết tại sao cow.moo.thing = 5 không làm việc, mặc dù cow.moo.thing khá rõ ràng mang lại cho tôi 10? Và tại sao cow.moo.__func__.thing = 5 hoạt động? Tôi không có ý tưởng tại sao nó, nhưng trong ngẫu nhiên fiddling với các công cụ trong danh sách dir(cow.moo) cố gắng để có được một cái gì đó để làm việc nó đột nhiên đã làm, và tôi không có ý tưởng tại sao.

Trả lời

33

Để tra cứu thuộc tính, Python tự động sử dụng hàm thực được đính kèm với phương pháp thể hiện cho bạn.

Để thiết lập thuộc tính, nó không phải là.

Chúng là hai hoạt động riêng biệt tùy thuộc vào bên nào của câu lệnh bạn đang sử dụng, mặc dù cả hai đều sử dụng toán tử ..

Khi bạn truy cập vào phương thức thể hiện __func__, bạn đang truy cập theo cách thủ công hàm thực sự thực sự có thuộc tính moo.

Trong Python 3, thao tác này sẽ hoạt động như bạn muốn/mong đợi vì các phương thức cơ bản chỉ hoạt động.

+0

Ah ok, tôi không bao giờ biết. Cảm ơn! –

+0

Xin lỗi vì đã hồi sinh một bài đăng cũ nhưng trong Python3 'bò(). Moo.thing = 5' đang trả về đối tượng' AttributeError: 'method' không có thuộc tính 'thing''. Bạn có biết tại sao ? –

+0

@JacquesGaudin Trên cá thể ('bò(). Moo') hàm được bao bọc trong một đối tượng phương thức trong bất kỳ phiên bản Python nào - sự khác biệt là trên lớp (' cow.moo') nó không được gói trong Python 3. Các gói là cần thiết cho 'tự' để có được thông qua tự động đến chức năng. – agf

3

Nếu bạn đang tìm cách sửa đổi các thuộc tính hàm của cả hàm và phương thức mẫu từ C thì bạn phải kiểm tra loại có thể gọi được.

Vì vậy, giả sử bạn có một PyObject của một số loại callable bạn có thể kiểm tra xem nó như thế này:

PyObject *callable; // set to something callable 
PyObject *setting; // set to something 
if(PyMethod_Check(callable)){ 
    PyObject_SetAttrString(PyMethod_Function(callable),"attribute",setting); 
}else{ 
    PyObject_SetAttrString(callable,"attribute",setting); 
} 
... 
// and the inverse 
if(PyMethod_Check(callable){   
    if(PyObject_HasAttrString(PyMethod_Function(callable),"attribute")){ 
     PyObject_DelAttrString(PyMethod_Function(callable),"attribute"); 
    } 
    }else{ 
    if(PyObject_HasAttrString(callable,"attribute")){ 
     PyObject_DelAttrString(callable,"attribute"); 
    } 
    } 

Bây giờ mã AGF chỉ ra tác phẩm từ bên trong Python cho các phương pháp dụ. Nếu tôi chỉ cố gắng thiết lập thuộc tính của phương thức instance, nó sẽ không tìm thấy thuộc tính bất kể tôi đã cố gắng truy cập nó từ Python như thế nào.

Tôi gặp phải vấn đề này và câu hỏi của Li Haoyi với câu trả lời của câu trả lời đã giúp tôi hiểu những gì cần phải thay đổi. Tôi tìm ai đó sẽ tìm thấy câu hỏi này và trả lời một lần nữa trong khi tìm kiếm cách giải quyết vấn đề này thông qua C.

Edit: Lưu ý: Đây là dành cho Python 2.7.x. Python 3.x sử dụng các cuộc gọi hàm khác nhau.

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