假设我有如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用获取函数的名称foo.func_name
。如上所述,我如何以编程方式获取其源代码?
foo.__name__
假设我有如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用获取函数的名称foo.func_name
。如上所述,我如何以编程方式获取其源代码?
foo.__name__
Answers:
如果该功能来自文件系统上可用的源文件,那么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
但是我相信,如果函数是从字符串,流中编译的,或者是从编译文件中导入的,那么您将无法检索其源代码。
len
。在哪里可以找到该len
函数的源代码?
inspect.getsourcelines(foo)
该检查模块具有用于从Python对象中检索的源代码的方法。貌似它仅在源位于文件中时才起作用。如果有的话,我想您就不需要从对象中获取源代码。
python 3.5.3
解释器中使用inspect 。import inspect
+ inspect.getsource(foo)
工作正常。
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
如果使用的是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
dir(MyClass)
,then MyClass.__init__??
等来还原它。
虽然我通常会认为这inspect
是一个很好的答案,但我不同意您无法获得解释器中定义的对象的源代码。如果使用dill.source.getsource
from dill
,即使它们是交互式定义的,也可以获取函数和lambda的来源。它也可以从咖喱中定义的绑定或未绑定类方法和函数中获取代码……但是,如果没有封闭对象的代码,您可能无法编译该代码。
>>> 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
>>>
dill.source.getsource
检查解释器的历史记录中的函数,类,lambda等,而不检查传递给exec的字符串的内容。
dill
回答这个问题:stackoverflow.com/questions/13827543/...
dill.source
具有和的功能getname
,importable
并且getsource
专注于获取任何给定对象的源代码(或产生对象的可导入对象)。对于像一个简单的事情int
有没有源,因此如预期它不工作(即,对于“α= 10”,它返回“10”)。
>>> a = 10; print( [key for key, val in globals().items() if val is a][0] )
dill
,但我的回答仍有待改进(IE,如果您使用多个名称表示相同的值,则无法确定使用了哪个名称。如果您传递一个表达式,它不能说出那个表达式是什么。哎呀,如果您传递一个表达式,该表达式的值与一个名称相同,它将改为使用该名称。)可以dill
解决我的答案中的任何缺点此处:stackoverflow.com/a/28634996/901641
扩展runeh的答案:
>>> 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
编辑:正如@ 0sh所指出的,此示例使用ipython
但不是plain可以工作python
。但是,从源文件导入代码时,两者都应该很好。
getsource(foo)
。
您可以使用inspect
模块来获取完整的源代码。你必须使用getsource()
方法为从inspect
模块。例如:
import inspect
def get_my_code():
x = "abcd"
return x
print(inspect.getsource(get_my_code))
您可以在下面的链接中查看更多选项。 检索您的python代码
由于此帖子被标记为与其他帖子重复,因此我在这里针对“ 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))
它正确产生
def foo(arg1, arg2):
# do something with args
a = arg1 + arg2
return a
x ** 2
有关详细信息,请参见mini-lambda
文档。我是作者;)
请注意,只有在单独的行上给出lambda时,可接受的答案才有效。如果将其作为参数传递给函数,并希望将lambda的代码作为对象进行检索,则问题将变得有些棘手,因为这inspect
将为您提供整行内容。
例如,考虑一个文件test.py
:
import inspect
def main():
x, f = 3, lambda a: a + 1
print(inspect.getsource(f))
if __name__ == "__main__":
main()
执行它会给你(注意缩进!):
x, f = 3, lambda a: a + 1
我认为,要检索lambda的源代码,最好的办法是重新解析整个源文件(使用f.__code__.co_filename
),并通过行号及其上下文匹配lambda AST节点。
我们必须在按合同设计的库icontract中做到这一点,因为我们必须解析作为装饰器参数传入的lambda函数。在此处粘贴太多代码,因此请看一下此函数的实现。
如果您要严格定义函数,并且定义相对简短,那么没有依赖性的解决方案是在字符串中定义函数并将表达式的eval()分配给函数。
例如
funcstring = 'lambda x: x> 5'
func = eval(funcstring)
然后可以选择将原始代码附加到该函数:
func.source = funcstring