在 lambda 中访问函数的 __doc__
Accessing __doc__ of function inside a lambda
我想提取一个函数的文档字符串,一旦它被包装在 lambda
。
考虑以下示例:
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": lambda: foo(2),
}
for k, v in dct.items()
print(k, v(), v.__doc__)
我得到:
a 1 Foo docstring
b 2 None
如何引用“调用”lambda
时调用的函数?
更新
感谢所有回答:
from functools import partial
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": partial(foo, 2),
}
for k, v in dct.items():
if hasattr(v, "func"):
print(k, v(), v.func.__doc__)
else:
print(k, v(), v.__doc__)
a 1 Foo docstring
b 2 Foo docstring
没有“好的”方法来做到这一点。但是,使用 inspect
模块在技术上是可行的。这是一个非常脆弱的实现,适合您获取 lambda 调用的第一个函数的文档字符串的用例:
import inspect
import re
def get_docstring_from_first_called_function(func):
# the inspect module can get the source code
func_source = inspect.getsource(func)
# very silly regex that gets the name of the first function
name_of_first_called_function = re.findall(r'\w+|\W+', func_source.split("(")[0])[-1]
# if the function is defined at the top level, it will be in `globals()`
first_called_function = globals()[name_of_first_called_function]
return first_called_function.__doc__
def foo(a=1):
"""Foo docstring"""
return a
b = lambda: foo(2)
print(get_docstring_from_first_called_function(b))
> Foo docstring
正如我所说,这个实现是脆弱的。例如,如果调用的第一个函数不在 globals
中,它会立即中断。但是,如果您发现自己处于非常困难的境地,您可能可以为您的用例拼凑出一个解决方案。
但是,如果可能的话,您应该改用 functools
import functools
def foo(a=1):
"""Foo docstring"""
return a
b = functools.partial(foo, 2)
print(b.func.__doc__)
好吧,尝试向 smt 添加文档等功能,根据定义应该是“匿名的”...只能通过一种棘手的方式来完成。
我可以使用嵌套装饰器来实现。
首先注意print('__doc__' in dir(lambda: ''))
是True
.
def add_doc_to_lambda(func, a, docs=''):
# also provide custom docs parameter
if docs == '':
return (lambda l: (lambda _=setattr(l, '__doc__', func.__doc__): l)())(lambda: func(a))
return (lambda l: (lambda _=setattr(l, '__doc__', docs): l)())(lambda: func(a))
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": add_doc_to_lambda(foo, 2), # add_doc_to_lambda(foo, 2, 'lambda docs') # case of custom docs
}
for k, v in dct.items():
print('>>> ', k, v(), v.__doc__)
输出
>>> a 1 Foo docstring
>>> b 2 Foo docstring # lambda docs # case custom docs
备注:
add_doc_to_lambda
可调用
print(dct['b'])
<function dec.<locals>.<lambda> at 0x7f6eda92ee50>
- 还有更直接的方式如
l = lambda: foo(2)
l.__doc__ = foo.__doc__
print(l.__doc__)
可行,但将 lambda 函数赋值给变量是一种不好的做法。
我建议您使用不同的机制 lambda
may be appropriate here. Anything that returns a properly wrapped FunctionType
is going to have direct access to the correct __doc__
. One common method would be to use functools.partial
with functools.wraps
:
from functools import partial, wraps
dct = {
"a": foo,
"b": wraps(foo)(partial(foo, 2)),
}
我想提取一个函数的文档字符串,一旦它被包装在 lambda
。
考虑以下示例:
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": lambda: foo(2),
}
for k, v in dct.items()
print(k, v(), v.__doc__)
我得到:
a 1 Foo docstring
b 2 None
如何引用“调用”lambda
时调用的函数?
更新
感谢所有回答:
from functools import partial
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": partial(foo, 2),
}
for k, v in dct.items():
if hasattr(v, "func"):
print(k, v(), v.func.__doc__)
else:
print(k, v(), v.__doc__)
a 1 Foo docstring
b 2 Foo docstring
没有“好的”方法来做到这一点。但是,使用 inspect
模块在技术上是可行的。这是一个非常脆弱的实现,适合您获取 lambda 调用的第一个函数的文档字符串的用例:
import inspect
import re
def get_docstring_from_first_called_function(func):
# the inspect module can get the source code
func_source = inspect.getsource(func)
# very silly regex that gets the name of the first function
name_of_first_called_function = re.findall(r'\w+|\W+', func_source.split("(")[0])[-1]
# if the function is defined at the top level, it will be in `globals()`
first_called_function = globals()[name_of_first_called_function]
return first_called_function.__doc__
def foo(a=1):
"""Foo docstring"""
return a
b = lambda: foo(2)
print(get_docstring_from_first_called_function(b))
> Foo docstring
正如我所说,这个实现是脆弱的。例如,如果调用的第一个函数不在 globals
中,它会立即中断。但是,如果您发现自己处于非常困难的境地,您可能可以为您的用例拼凑出一个解决方案。
但是,如果可能的话,您应该改用 functools
import functools
def foo(a=1):
"""Foo docstring"""
return a
b = functools.partial(foo, 2)
print(b.func.__doc__)
好吧,尝试向 smt 添加文档等功能,根据定义应该是“匿名的”...只能通过一种棘手的方式来完成。 我可以使用嵌套装饰器来实现。
首先注意print('__doc__' in dir(lambda: ''))
是True
.
def add_doc_to_lambda(func, a, docs=''):
# also provide custom docs parameter
if docs == '':
return (lambda l: (lambda _=setattr(l, '__doc__', func.__doc__): l)())(lambda: func(a))
return (lambda l: (lambda _=setattr(l, '__doc__', docs): l)())(lambda: func(a))
def foo(a=1):
"""Foo docstring"""
return a
dct = {
"a": foo,
"b": add_doc_to_lambda(foo, 2), # add_doc_to_lambda(foo, 2, 'lambda docs') # case of custom docs
}
for k, v in dct.items():
print('>>> ', k, v(), v.__doc__)
输出
>>> a 1 Foo docstring
>>> b 2 Foo docstring # lambda docs # case custom docs
备注:
add_doc_to_lambda
可调用
print(dct['b'])
<function dec.<locals>.<lambda> at 0x7f6eda92ee50>
- 还有更直接的方式如
l = lambda: foo(2)
l.__doc__ = foo.__doc__
print(l.__doc__)
可行,但将 lambda 函数赋值给变量是一种不好的做法。
我建议您使用不同的机制 lambda
may be appropriate here. Anything that returns a properly wrapped FunctionType
is going to have direct access to the correct __doc__
. One common method would be to use functools.partial
with functools.wraps
:
from functools import partial, wraps
dct = {
"a": foo,
"b": wraps(foo)(partial(foo, 2)),
}