获取没有定义行的 Python 函数的源代码

Aar*_*sen 2 python function

使用该inspect.getsourcelines函数,我可以获得如下 Python 函数的源代码:

import inspect    

def some_decorator(x):
    return x

@some_decorator
def foo():
    print("bar")

print(inspect.getsourcelines(foo)[0])
Run Code Online (Sandbox Code Playgroud)

此代码将正确地将函数的源代码行输出为列表:

['@some_decorator\n', 'def foo():\n', '    print("bar")\n']
Run Code Online (Sandbox Code Playgroud)

但是,我只想要函数内部的代码,而不是整个函数声明。所以我只想要这个输出(还要注意正确的缩进):

['print("bar")\n']
Run Code Online (Sandbox Code Playgroud)

我尝试使用切片和 astrip来删除前两行,然后删除缩进,但这不适用于许多函数,我必须相信有更好的方法。

inspect模块或我可以使用的其他模块pip install是否具有此功能?

tho*_*len 5

如果定义超过一行并且使用注释(因为注释引入了额外的“:”),则接受的答案中的两个解决方案就会中断。在下文中,我也处理这种情况(但不处理已接受答案的第二个函数中包含的异步情况。

import inspect
from itertools import dropwhile


def get_function_body(func):
    source_lines = inspect.getsourcelines(func)[0]
    source_lines = dropwhile(lambda x: x.startswith('@'), source_lines)
    line = next(source_lines).strip()
    if not line.startswith('def '):
        return line.rsplit(':')[-1].strip()
    elif not line.endswith(':'):
        for line in source_lines:
            line = line.strip()
            if line.endswith(':'):
                break
    # Handle functions that are not one-liners  
    first_line = next(source_lines)
    # Find the indentation of the first line    
    indentation = len(first_line) - len(first_line.lstrip())
    return ''.join([first_line[indentation:]] + [line[indentation:] for line in source_lines])
Run Code Online (Sandbox Code Playgroud)

例如,应用于:

# A pre comment
def f(a, b: str, c='hello', 
      d: float=0.0, *args, **kwargs) -> str:
    """The docs"""
    return f"{c} {b}: {a + d}"

print(get_function_body(f))
Run Code Online (Sandbox Code Playgroud)

我明白了

"""The docs"""
return f"{c} {b}: {a + d}"
Run Code Online (Sandbox Code Playgroud)