Skip to content
Advertisement

Accessing __doc__ of function inside a lambda

I would like to extract the docstring of a function once it has been wrapped in lambda.

Consider the following example:

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__)

I get:

a 1 Foo docstring
b 2 None

How can I reference the function called on “calling” the lambda one?

Update

Thanks for all answers:

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

Advertisement

Answer

There is no “good” way to do this. However, it is technically possible using the inspect module. Here is a very brittle and fragile implementation that fits your use case of getting the docstring of the first function called by a 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

As I said, this implementation is fragile and brittle. For instance, it breaks instantly if the first function called is not in globals. But if you find yourself in very dire straits, you can probably hack together a solution for your use case.

If at all possible, however, you should use functools instead

import functools

def foo(a=1):
    """Foo docstring"""
    return a

b = functools.partial(foo, 2)

print(b.func.__doc__)
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement