如何记录对复杂 API 函数的小改动?
How to document small changes to complex API functions?
假设我们有一个从某个库导入的复杂 API 函数。
def complex_api_function(
number, <lots of positional arguments>,
<lots of keyword arguments>):
'''really long docstring'''
# lots of code
我想围绕该函数编写一个简单的包装器以进行微小的更改。 例如,应该可以将第一个参数作为字符串传递。如何记录这个?我考虑了以下选项:
选项 1:
def my_complex_api_function(number_or_str, *args, **kwargs):
'''
Do something complex.
Like `complex_api_function`, but first argument can be a string.
Parameters
----------
number_or_str : int or float or str
Can be a number or a string that can be interpreted as a float.
<copy paste description from complex_api_function docstring>
*args
Positional arguments passed to `complex_api_function`.
**kwargs
Keyword arguments passed to `complex_api_function`.
Returns
-------
<copy paste from complex_api_function docstring>
Examples
--------
<example where first argument is a string, e.g. '-5.0'>
'''
return complex_api_function(float(number_or_str), *args, **kwargs)
缺点:用户必须查看 complex_api_function
的文档才能获得
关于 *args
和 **kwargs
的信息。 complex_api_function
中的复制粘贴部分发生变化时需要调整。
选项 2:
复制并粘贴 complex_api_function
的签名(而不是使用 *args
和 **kwargs
)及其文档字符串。对提到第一个参数也可以是字符串的文档字符串进行微小的更改。添加示例。
缺点:冗长,必须在 complex_api_function
更改时更改。
选项 3:
用functools.wraps(complex_api_function)
装饰my_complex_api_function
。
缺点:没有资料说number
也可以是字符串
我正在寻找一个与 my_complex_api_function
中的变化细节无关的答案。该程序应该适用于对原始 complex_api_function
.
的任何微小调整
您可以使用 附录 自动执行原始文档字符串的 "specialization"。例如,pydoc is using the special attribute __doc__
。您可以编写一个装饰器,用您的附录自动覆盖原始函数 __doc__
。
例如:
def extend_docstring(original, addendum):
def callable(func):
func.__doc__ = original + addendum
return func
return callable
def complex_api_function(a, b, c):
'''
This is a very complex function.
Parameters
----------
a: int or float
This is the argument A.
b: ....
'''
print('do something')
@extend_docstring(
complex_api_function.__doc__,
'''
Addendum
--------
Parameter a can also be a string
'''
)
def my_complex_api_function(a, b, c):
return complex_api_function(float(a), b, c)
或...
def extend_docstring(original):
def callable(func):
func.__doc__ = original + func.__doc__
return func
return callable
def complex_api_function(a, b, c):
'''
This is a very complex function.
Parameters
----------
a: int or float
This is the argument A.
b: ....
'''
print('do something')
@extend_docstring(complex_api_function.__doc__)
def my_complex_api_function(a, b, c):
'''
Addendum
--------
Parameter a can also be a string
'''
return complex_api_function(float(a), b, c)
如果你 运行 pydoc (pydoc3 -w my_module.py
) 它会产生:preview of html generated by pydoc
补充说明:
如果您使用 Python 3,您可以使用 annotations 来记录函数参数的类型。它提供了很多好处,而不仅仅是文档。例如:
from typing import Union
def my_complex_api_function(number_or_str: Union[int, float, str], *args, **kwargs):
我推荐如下内容:
def my_complex_api_function(number_or_str, *args, **kwargs):
"""This function is a light wrapper to `complex_api_function`.
It allows you to pass a string or a number, whereas `complex_api_function` requires a
number. See :ref:`complex_api_function` for more details.
:param number_or_str: number or str to convert to a number and pass to `complex_api_function`.
:param args: Arguments to pass to `complex_api_function`
:param kwargs: Keyword arguments to pass to `complex_api_function`
:return: Output of `complex_api_function`, called with passed parameters
"""
这句话简洁明了。但也请记住,如果使用像 sphinx 这样的文档系统,要 link 具有 :ref:`bob`
或类似的功能。
不确定这是否是您要查找的内容,但这有助于完全避免该问题。
def first_as_num_or_str(func):
'''Decorator allowing the first parameter of the given function to be a number or a string
:param func: A function whose first argument is a number
:return: `func`, but now the first argument is cast to a float
'''
def new_func(*args, **kwargs):
func(float(args[0]), args[1:], kwargs)
return new_func
wrapped_api_func = first_as_num_or_str(complex_api_function)
假设我们有一个从某个库导入的复杂 API 函数。
def complex_api_function(
number, <lots of positional arguments>,
<lots of keyword arguments>):
'''really long docstring'''
# lots of code
我想围绕该函数编写一个简单的包装器以进行微小的更改。 例如,应该可以将第一个参数作为字符串传递。如何记录这个?我考虑了以下选项:
选项 1:
def my_complex_api_function(number_or_str, *args, **kwargs):
'''
Do something complex.
Like `complex_api_function`, but first argument can be a string.
Parameters
----------
number_or_str : int or float or str
Can be a number or a string that can be interpreted as a float.
<copy paste description from complex_api_function docstring>
*args
Positional arguments passed to `complex_api_function`.
**kwargs
Keyword arguments passed to `complex_api_function`.
Returns
-------
<copy paste from complex_api_function docstring>
Examples
--------
<example where first argument is a string, e.g. '-5.0'>
'''
return complex_api_function(float(number_or_str), *args, **kwargs)
缺点:用户必须查看 complex_api_function
的文档才能获得
关于 *args
和 **kwargs
的信息。 complex_api_function
中的复制粘贴部分发生变化时需要调整。
选项 2:
复制并粘贴 complex_api_function
的签名(而不是使用 *args
和 **kwargs
)及其文档字符串。对提到第一个参数也可以是字符串的文档字符串进行微小的更改。添加示例。
缺点:冗长,必须在 complex_api_function
更改时更改。
选项 3:
用functools.wraps(complex_api_function)
装饰my_complex_api_function
。
缺点:没有资料说number
也可以是字符串
我正在寻找一个与 my_complex_api_function
中的变化细节无关的答案。该程序应该适用于对原始 complex_api_function
.
您可以使用 附录 自动执行原始文档字符串的 "specialization"。例如,pydoc is using the special attribute __doc__
。您可以编写一个装饰器,用您的附录自动覆盖原始函数 __doc__
。
例如:
def extend_docstring(original, addendum):
def callable(func):
func.__doc__ = original + addendum
return func
return callable
def complex_api_function(a, b, c):
'''
This is a very complex function.
Parameters
----------
a: int or float
This is the argument A.
b: ....
'''
print('do something')
@extend_docstring(
complex_api_function.__doc__,
'''
Addendum
--------
Parameter a can also be a string
'''
)
def my_complex_api_function(a, b, c):
return complex_api_function(float(a), b, c)
或...
def extend_docstring(original):
def callable(func):
func.__doc__ = original + func.__doc__
return func
return callable
def complex_api_function(a, b, c):
'''
This is a very complex function.
Parameters
----------
a: int or float
This is the argument A.
b: ....
'''
print('do something')
@extend_docstring(complex_api_function.__doc__)
def my_complex_api_function(a, b, c):
'''
Addendum
--------
Parameter a can also be a string
'''
return complex_api_function(float(a), b, c)
如果你 运行 pydoc (pydoc3 -w my_module.py
) 它会产生:preview of html generated by pydoc
补充说明: 如果您使用 Python 3,您可以使用 annotations 来记录函数参数的类型。它提供了很多好处,而不仅仅是文档。例如:
from typing import Union
def my_complex_api_function(number_or_str: Union[int, float, str], *args, **kwargs):
我推荐如下内容:
def my_complex_api_function(number_or_str, *args, **kwargs):
"""This function is a light wrapper to `complex_api_function`.
It allows you to pass a string or a number, whereas `complex_api_function` requires a
number. See :ref:`complex_api_function` for more details.
:param number_or_str: number or str to convert to a number and pass to `complex_api_function`.
:param args: Arguments to pass to `complex_api_function`
:param kwargs: Keyword arguments to pass to `complex_api_function`
:return: Output of `complex_api_function`, called with passed parameters
"""
这句话简洁明了。但也请记住,如果使用像 sphinx 这样的文档系统,要 link 具有 :ref:`bob`
或类似的功能。
不确定这是否是您要查找的内容,但这有助于完全避免该问题。
def first_as_num_or_str(func):
'''Decorator allowing the first parameter of the given function to be a number or a string
:param func: A function whose first argument is a number
:return: `func`, but now the first argument is cast to a float
'''
def new_func(*args, **kwargs):
func(float(args[0]), args[1:], kwargs)
return new_func
wrapped_api_func = first_as_num_or_str(complex_api_function)