假设我有一个如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用foo.func_name获取函数的名称。我如何通过编程获得它的源代码,就像我上面键入的那样?
假设我有一个如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用foo.func_name获取函数的名称。我如何通过编程获得它的源代码,就像我上面键入的那样?
当前回答
我相信变量名没有存储在pyc/pyd/pyo文件中,因此如果没有源文件,就无法检索准确的代码行。
其他回答
如果函数来自文件系统中可用的源文件,那么inspect.getsource(foo)可能会有帮助:
如果foo被定义为:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
然后:
import inspect
lines = inspect.getsource(foo)
print(lines)
返回:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
但我相信,如果函数是从字符串、流或从编译文件导入的,那么你就不能检索它的源代码。
我相信变量名没有存储在pyc/pyd/pyo文件中,因此如果没有源文件,就无法检索准确的代码行。
总结一下:
import inspect
print( "".join(inspect.getsourcelines(foo)[0]))
拉法łDowgird朋友与答案:
我相信,如果函数是从字符串、流或从编译文件导入的,那么你就不能检索它的源代码。
但是,可以检索从字符串编译的函数的源代码,前提是编译代码还向lineecache添加了一个条目。缓存dict类型:
import linecache
import inspect
script = '''
def add_nums(a, b):
return a + b
'''
bytecode = compile(script, 'unique_filename', 'exec')
tmp = {}
eval(bytecode, {}, tmp)
add_nums = tmp["add_nums"]
linecache.cache['unique_filename'] = (
len(script),
None,
script.splitlines(True),
'unique_filename',
)
print(inspect.getsource(add_nums))
# prints:
# """
# def add_nums(a, b):
# return a + b
# """
这就是attrs库如何自动为类创建各种方法,给定一组类期望初始化的属性。点击这里查看他们的源代码。正如源代码所解释的,这是一个主要用于使调试器(如PDB)能够逐级遍历代码的特性。
由于这篇文章被标记为另一篇文章的副本,我在这里回答“lambda”情况,尽管OP不是关于lambdas的。
因此,对于没有在自己的行中定义的lambda函数:除了marko。在ristin的回答中,您可能希望使用mini-lambda或使用此回答中建议的SymPy。
Mini-lambda更轻,支持任何类型的操作,但只适用于单个变量 SymPy更重,但配备了更多的数学/微积分运算。特别是它可以简化你的表达。它还支持同一个表达式中的多个变量。
下面是使用mini-lambda的方法:
from mini_lambda import x, is_mini_lambda_expr
import inspect
def get_source_code_str(f):
if is_mini_lambda_expr(f):
return f.to_string()
else:
return inspect.getsource(f)
# test it
def foo(arg1, arg2):
# do something with args
a = arg1 + arg2
return a
print(get_source_code_str(foo))
print(get_source_code_str(x ** 2))
它会正确地产生
def foo(arg1, arg2):
# do something with args
a = arg1 + arg2
return a
x ** 2
详见mini-lambda文档。顺便说一下,我是作者;)