当前位置:  开发笔记 > 编程语言 > 正文

如何获取Python函数的源代码?

如何解决《如何获取Python函数的源代码?》经验,为你挑选了8个好方法。

假设我有一个如下定义的Python函数:

def foo(arg1,arg2):
    #do something with args
    a = arg1 + arg2
    return a

我可以使用函数的名称foo.func_name.如上所示,我如何以编程方式获取其源代码?



1> Rafał Dowgir..:

如果该函数来自文件系统上可用的源文件,那么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                

但我相信,如果函数是从字符串,流或从编译文件导入的,那么您无法检索其源代码.


这个答案没有明确提到它,但inspect.getsource(foo)在单个字符串中返回源代码而不是元组,其中元组[0]是行列表.如果您需要查看repl,则getsource将更有用
[返回](https://docs.python.org/2/library/inspect.html#inspect.getsourcelines)一个元组; tuple [0]是表示源代码行的字符串列表,tuple [1]是运行它的执行上下文中的行号.在IPython; 这是*单元格内的行号*不是整个*笔记本*

2> runeh..:

该检查模块具有用于从Python对象中检索的源代码的方法.看起来它只有在源位于文件中时才有效.如果你有,我想你不需要从对象获取源.


是的,它似乎只适用于文件中定义的对象.不适用于翻译中定义的那些.
令我惊讶的是,它也适用于Ipython/Jupyter笔记本电脑

3> schlamar..:

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


祝你把这些信息显示为QToolTip();)
@Noumenon因为他们在Python中通常没有源代码,所以它们是用C语言编写的

4> prashanth..:

如果你使用的是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/
Type:      function


非常有用的IPython和Jupyter笔记本如果/当你不小心删除了多个包含你刚刚花了一天时间创建和测试的函数的单元格时....

5> Mike McKerns..:

虽然我一般都认为这inspect是一个很好的答案,但我不同意你无法获得解释器中定义的对象的源代码.如果使用dill.source.getsourcefrom 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

>>> 



6> TomDotTom..:

为了扩展符文的答案:

>>> 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但不是普通的python.但是,从源文件导入代码时,两者都应该没问题.


这将无法工作,因为解释器会将foo编译为字节码并丢弃源代码,如果您尝试运行`getsource(foo)`则会引发OSError.

7> 小智..:

您可以使用inspect模块获取完整的源代码.你必须使用getsource()方法为从inspect模块.例如:

import inspect

def get_my_code():
    x = "abcd"
    return x

print(inspect.getsource(get_my_code))

您可以在以下链接中查看更多选项. 检索你的python代码



8> smarie..:

由于此帖子被标记为与其他帖子重复,因此我在这里针对“ 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 文档。我是作者;)

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有