2012-10-08 42 views
11

Hàm Python có đối tượng mã __code__.Lấy hàm Python cho đối tượng mã

A sys.settrace theo dõi frame có đối tượng mã f_code.

Đối với những cuộc gọi đến trình theo dõi đó là các hàm, làm cách nào tôi có thể nhận đối tượng hàm (và thành viên __annotation__)?

Cho đến nay, bằng cách thử và sai, tôi có:

if hasattr(frame.f_globals.get(frame.f_code.co_name),"__annotations__"): 

Điều này dường như làm việc cho các chức năng, nhưng không phải cho các chức năng đẳng cấp thành viên; tồi tệ hơn, nó gây nhầm lẫn với các hàm thành viên lớp với các hàm mức cao nhất của cùng một tên.

(. Tôi đang trên Python 3.2.3 (Xubuntu) Tôi thấy rằng Python 3.3 inspect mô-đun có chức năng signature, điều này sẽ trở lại với chú thích cho một đối tượng mã hoặc nó quá cần một đối tượng chức năng?)

Trả lời

5

Thông qua mô-đun inspect.getframeinfo. Ý tôi là - không có cách nào đơn giản để làm điều đó trong Python - Hầu hết các lần bạn có thể giữ đối tượng mã, mà không có chức năng đã có, đó là thông qua sự phân tách khung.

Chức năng getframeinfo của kiểm tra trả lại một số thông tin về khung đang chạy, sau đó bạn có thể truy xuất đối tượng hàm bằng cách lấy tên của nó.

Tough này là thực hiện phụ thuộc và có một số nhược điểm:

>>> import inspect 
>>> def a(): 
... return inspect.currentframe() 
... 

>>> inspect.getframeinfo(a()) 
Traceback(filename='<stdin>', lineno=2, function='a', code_context=None, index=None) 
>>> b = inspect.getframeinfo(a()) 
>>> b.function 
'a' 

Một cách khác, nhưng vẫn thực hiện phụ thuộc, là sử dụng các mô-đun gc (garbage collector) để có được dẫn đến nhiều để nói đối tượng mã.

>>> import gc 
>>> from types import FunctionType 
>>> def a(): pass 
... 
>>> code = a.__code__ 

>>> [obj for obj in gc.get_referrers(code) if isinstance(obj, FunctionType) ][0] 
<function a at 0x7f1ef4484500> 
>>> 

- này là dành cho Python 3 - cho Python 2 ta nên thay thế __code__ bởi func_code

+0

'lĩnh vực function'' cái inspect.getframeinfo' tuple dường như là một chuỗi chứ không phải là một đối tượng hàm. Và cách tiếp cận gc có nhiều rủi ro? – Will

+0

Tôi đã kết thúc bằng cách sử dụng gc.get_referrers (...) [0] – Will

+1

Bạn có thể thêm một kiểm tra để xem func_code/__ code__ là đối tượng mã bạn muốn hiểu danh sách hay không. Điều này vẫn không thành công nếu bạn tạo nhiều hàm với các đóng khác nhau từ cùng một đối tượng mã, ví dụ với một người trang trí. Giả sử ta có thể so sánh các f_locals với các cell_contents của func_closure cho mỗi ... –

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