2009-07-09 13 views
9

Tôi đang viết phần mở rộng C, và tôi muốn làm cho chữ ký của các phương pháp của tôi có thể nhìn thấy được để xem xét.Mở rộng Python C: chữ ký phương thức cho tài liệu?

static PyObject* foo(PyObject *self, PyObject *args) { 

    /* blabla [...] */ 

} 

PyDoc_STRVAR(
    foo_doc, 
    "Great example function\n" 
    "Arguments: (timeout, flags=None)\n" 
    "Doc blahblah doc doc doc."); 

static PyMethodDef methods[] = { 
    {"foo", foo, METH_VARARGS, foo_doc}, 
    {NULL}, 
}; 

PyMODINIT_FUNC init_myexample(void) { 
    (void) Py_InitModule3("_myexample", methods, "a simple example module"); 
} 

Bây giờ nếu (sau khi xây dựng nó ...) Tôi nạp module và nhìn vào sự giúp đỡ của nó:

>>> import _myexample 
>>> help(_myexample) 

tôi sẽ nhận được:

Help on module _myexample: 

NAME 
    _myexample - a simple example module 

FILE 
    /path/to/module/_myexample.so 

FUNCTIONS 
    foo(...) 
     Great example function 
     Arguments: (timeout, flags=None) 
     Doc blahblah doc doc doc. 

Tôi muốn trở thành cụ thể hơn và có thể thay thế foo (...) bởi foo (hết giờ, cờ = Không)

Tôi có thể làm điều này không? Làm sao?

Trả lời

6

Cách tiếp cận thông thường của tôi để tìm hiểu về những thứ như thế này là: "sử dụng nguồn".

Về cơ bản, tôi cho rằng các mô-đun chuẩn của python sẽ sử dụng tính năng này khi có sẵn. Nhìn vào nguồn (for example here) nên giúp đỡ, nhưng trên thực tế ngay cả các mô-đun tiêu chuẩn thêm nguyên mẫu sau khi đầu ra tự động. Như thế này:

[email protected]:~$ python2.6 
>>> import fcntl 
>>> help(fcntl.flock) 
flock(...) 
    flock(fd, operation) 

    Perform the lock operation op on file descriptor fd. See the Unix [...] 

Vì vậy, ngược dòng không sử dụng tính năng như vậy, tôi cho rằng nó không có ở đó. :-)

OK, tôi vừa kiểm tra các nguồn python3k hiện tại và đây vẫn là trường hợp. Chữ ký đó được tạo trong pydoc.py trong các nguồn trăn tại đây: pydoc.py. Đoạn trích có liên quan bắt đầu bằng dòng 1260:

 
     if inspect.isfunction(object): 
      args, varargs, varkw, defaults = inspect.getargspec(object) 
      ... 
     else: 
      argspec = '(...)' 

inspect.isfunction kiểm tra nếu đối tượng yêu cầu tài liệu là hàm Python. Nhưng các hàm được triển khai C được coi là nội trang dựng sẵn, do đó bạn sẽ luôn nhận được name(...) làm đầu ra.

3

Đã 7 năm nhưng bạn có thể bao gồm chữ ký cho hàm và lớp mở rộng C.

Bản thân Python sử dụng Argument Clinic để tạo chữ ký động. Sau đó, một số cơ chế tạo ra một __text_signature__ và điều này có thể được quan sát (ví dụ với help). @MartijnPieters giải thích quá trình này khá tốt trong this answer.

Bạn thực sự có thể nhận được các phòng khám lập luận từ python và làm điều đó một cách năng động nhưng tôi thích cách thủ công: Bổ sung thêm chữ ký vào docstring:

Trong trường hợp của bạn:

PyDoc_STRVAR(
    foo_doc, 
    "foo(timeout, flags=None, /)\n" 
    "--\n" 
    "\n" 
    "Great example function\n" 
    "Arguments: (timeout, flags=None)\n" 
    "Doc blahblah doc doc doc."); 

tôi đã sử dụng nhiều trong gói này: iteration_utilities/src. Vì vậy, để chứng minh rằng nó hoạt động tôi sử dụng một trong những chức năng C-mở rộng tiếp xúc bằng cách gói này:

>>> from iteration_utilities import minmax 
>>> help(minmax) 
Help on built-in function minmax in module iteration_utilities._cfuncs: 

minmax(iterable, /, key, default) 
    Computes the minimum and maximum values in one-pass using only 
    ``1.5*len(iterable)`` comparisons. Recipe based on the snippet 
    of Raymond Hettinger ([0]_) but significantly modified. 

    Parameters 
    ---------- 
    iterable : iterable 
     The `iterable` for which to calculate the minimum and maximum. 
[...] 

Các docstring cho chức năng này được định nghĩa this file.

Điều quan trọng là nhận ra rằng này là không thể cho python < 3.4 là gì và bạn cần phải làm theo một số quy tắc:

  • Bạn cần phải bao gồm --\n\n sau khi dòng định nghĩa chữ ký.

  • Chữ ký phải nằm trong dòng đầu tiên của chuỗi tài liệu.

  • Chữ ký phải hợp lệ, tức là foo(a, b=1, c) không thành công do không thể xác định đối số vị trí sau đối số với mặc định.

  • Bạn chỉ có thể cung cấp một chữ ký. Vì vậy, nó không hoạt động nếu bạn sử dụng một cái gì đó như:

    foo(a) 
    foo(x, a, b) 
    -- 
    
    Narrative documentation 
    
+0

Điều này làm việc với 'inspect.signature'? – Eric

+0

@Eric Có, miễn là nó tuân thủ các quy tắc của '__text_signature__' tôi đã đề cập ở trên. – MSeifert

+0

Âm thanh như một thứ mà 'numpy' cần bản vá cho – Eric