假设我有一个如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Run Code Online (Sandbox Code Playgroud)
我可以使用函数的名称foo.func_name
.如上所示,我如何以编程方式获取其源代码?
Raf*_*ird 499
如果该函数来自文件系统上可用的源文件,那么inspect.getsource(foo)
可能会有所帮助:
如果foo
定义为:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Run Code Online (Sandbox Code Playgroud)
然后:
import inspect
lines = inspect.getsource(foo)
print(lines)
Run Code Online (Sandbox Code Playgroud)
返回:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Run Code Online (Sandbox Code Playgroud)
但我相信,如果函数是从字符串,流或从编译文件导入的,那么您无法检索其源代码.
sch*_*mar 81
dis
如果源代码不可用,那么这是你的朋友:
>>> import dis
>>> def foo(arg1,arg2):
... #do something with args
... a = arg1 + arg2
... return a
...
>>> dis.dis(foo)
3 0 LOAD_FAST 0 (arg1)
3 LOAD_FAST 1 (arg2)
6 BINARY_ADD
7 STORE_FAST 2 (a)
4 10 LOAD_FAST 2 (a)
13 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
pra*_*nth 73
如果你使用的是IPython,那么你需要输入"foo ??"
In [19]: foo??
Signature: foo(arg1, arg2)
Source:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
File: ~/Desktop/<ipython-input-18-3174e3126506>
Type: function
Run Code Online (Sandbox Code Playgroud)
Mik*_*rns 57
虽然我一般都认为这inspect
是一个很好的答案,但我不同意你无法获得解释器中定义的对象的源代码.如果使用dill.source.getsource
from dill
,则可以获取函数和lambdas的来源,即使它们是以交互方式定义的.它还可以从curries中定义的绑定或非绑定类方法和函数中获取代码...但是,如果没有封闭对象的代码,您可能无法编译该代码.
>>> from dill.source import getsource
>>>
>>> def add(x,y):
... return x+y
...
>>> squared = lambda x:x**2
>>>
>>> print getsource(add)
def add(x,y):
return x+y
>>> print getsource(squared)
squared = lambda x:x**2
>>>
>>> class Foo(object):
... def bar(self, x):
... return x*x+x
...
>>> f = Foo()
>>>
>>> print getsource(f.bar)
def bar(self, x):
return x*x+x
>>>
Run Code Online (Sandbox Code Playgroud)
Tom*_*Tom 21
为了扩展符文的答案:
>>> def foo(a):
... x = 2
... return x + a
>>> import inspect
>>> inspect.getsource(foo)
u'def foo(a):\n x = 2\n return x + a\n'
print inspect.getsource(foo)
def foo(a):
x = 2
return x + a
Run Code Online (Sandbox Code Playgroud)
编辑:正如@ 0sh所指出的,这个例子可以使用ipython
但不是普通的python
.但是,从源文件导入代码时,两者都应该没问题.
小智 11
您可以使用inspect
模块获取完整的源代码.你必须使用getsource()
方法为从inspect
模块.例如:
import inspect
def get_my_code():
x = "abcd"
return x
print(inspect.getsource(get_my_code))
Run Code Online (Sandbox Code Playgroud)
您可以在以下链接中查看更多选项. 检索你的python代码
总结:
import inspect
print( "".join(inspect.getsourcelines(foo)[0]))
Run Code Online (Sandbox Code Playgroud)
请注意,仅当 lambda 在单独的行中给出时,接受的答案才有效。如果您将它作为参数传递给函数并希望将 lambda 的代码作为对象检索,则问题会变得有点棘手,因为inspect
它将为您提供整行。
例如,考虑一个文件test.py
:
import inspect
def main():
x, f = 3, lambda a: a + 1
print(inspect.getsource(f))
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
执行它会给你(注意缩进!):
x, f = 3, lambda a: a + 1
Run Code Online (Sandbox Code Playgroud)
要检索 lambda 的源代码,在我看来,最好的办法是重新解析整个源文件(通过使用f.__code__.co_filename
)并通过行号及其上下文匹配 lambda AST 节点。
我们必须在我们的按合同设计库icontract 中精确地做到这一点,因为我们必须解析作为参数传递给装饰器的 lambda 函数。代码太多这里就不贴了,看一下这个函数的实现。
由于此帖子被标记为与其他帖子重复,因此我在这里针对“ lambda”案例回答,尽管OP与lambda无关。
因此,对于未在自己的行中定义的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))
Run Code Online (Sandbox Code Playgroud)
它正确产生
def foo(arg1, arg2):
# do something with args
a = arg1 + arg2
return a
x ** 2
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参见mini-lambda
文档。我是作者;)
小智 5
如果您自己严格定义该函数并且它是一个相对较短的定义,则没有依赖项的解决方案是在字符串中定义该函数并将表达式的 eval() 分配给您的函数。
例如
funcstring = 'lambda x: x> 5'
func = eval(funcstring)
Run Code Online (Sandbox Code Playgroud)
然后可以选择将原始代码附加到函数中:
func.source = funcstring
Run Code Online (Sandbox Code Playgroud)