Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何处理”的局限性;检查.getsource";-或者如何只获取函数的源?_Python_Python 3.x_Inspect - Fatal编程技术网

Python 如何处理”的局限性;检查.getsource";-或者如何只获取函数的源?

Python 如何处理”的局限性;检查.getsource";-或者如何只获取函数的源?,python,python-3.x,inspect,Python,Python 3.x,Inspect,我一直在玩Python标准库中的inspect模块 以下示例工作正常(假设已导入inspect): def foo(x,y): 返回x-y 打印(inspect.getsource(foo)) 。。。将打印def foo(x,y):\n返回x-y\n和 bar=lambda x,y:x/y 打印(检查.获取源(条形)) 。。。将打印bar=lambda x,y:x/y\n。到现在为止,一直都还不错。然而,在以下示例中,情况变得有点奇怪: 打印(inspect.getsource(lambda

我一直在玩Python标准库中的
inspect
模块

以下示例工作正常(假设已导入
inspect
):

def foo(x,y):
返回x-y
打印(inspect.getsource(foo))
。。。将打印
def foo(x,y):\n返回x-y\n

bar=lambda x,y:x/y
打印(检查.获取源(条形))
。。。将打印
bar=lambda x,y:x/y\n
。到现在为止,一直都还不错。然而,在以下示例中,情况变得有点奇怪:

打印(inspect.getsource(lambda x,y:x/y))
。。。将打印
打印(inspect.getsource(lambda x,y:x/y))

baz=[2,3,λx,y:x/y,5]
打印(inspect.getsource(baz[2]))
。。。将打印
baz=[2,3,lambda x,y:x/y,5]

模式似乎是所有相关的源代码都由
getsource
返回,而不管上下文如何。在我的例子中,除了所需的函数源/定义之外,这些行中的所有其他内容也包括在内。是否有另一种“替代”方法,允许以某种匿名方式提取表示函数源代码的内容,并且只提取其源代码


编辑(1)


。。。将打印
def foo(x,y):\n返回x-y\n

不幸的是,
inspect
无法执行此操作,并且如果不再次解析(和编译)源代码,它不可能工作
inspect
的方法相当有限:它用于调用then,这实质上是打开对象,直到我们到达一个目标

此时,我们正在处理编译的字节码。原始源代码中剩下的所有内容都是
co\u firstlineno

/*字节码对象*/
类型定义结构{
/*…省略了其他字段*/
int co_firstlineno;/*第一个源行号*/
PyObject*co_代码;/*指令操作码*/
/*…省略了其他字段*/
}PyCodeObject;
顺便说一句,类似于
PyCodeObject
,a,但没有列,这解释了为什么回溯只包括文件名和行:列没有编译成字节码

由于字节码不包含(第一)行以外的任何特定区域,因此无法从
inspect
或任何其他只使用(公共)字节码信息而不进行进一步解析的库中获取准确的源位置。这也适用于仅使用字节码的任何其他选项,例如
pickle

inspect
使用公共信息(
co_firstlineno
)和。然而,
inspect
几乎就在那里了,但它只找到了,而且它现在无法找到正确的
inspect
标记整行代码,并且不是从正确的变体开始的,它也不知道正确的对应源代码区域

假设我们有

加,减,mult=lambda x:x+1,lambda y:y-1,lambda z:z*5
我们只需要
减去
。由于字节码不包含
co_firstcolumn
,因此我们只有完整的行可用。我们可以解析所有的lambda,但是我们仍然不知道哪个lambda适合我们的
co\u代码
。我们需要再次编译它们,并检查它们的字节码是否与原始字节码相符


最后,我们必须做到这一点:再次解析源代码并找到正确的
PyCodeObject
。如果我们至少有一个起始列号,这会容易得多,因为我们可以只使用语法分析,但AST只保留。因此,
inspect
需要一个大补丁,或者字节码需要包含编译对象的起始列。

也许这会有所帮助:@cglace谢谢你的想法。我查看了它的源代码并对其进行了测试。在我的问题的上下文中,它是一个略微改进的包装器,围绕着
inspect.getsource
,涵盖了一些边缘情况,比如交互环境中定义的函数。但这并不能解决我的根本问题——这里没有区别。你“只”需要捕获lambdas吗?如果是,那么也许可以编写一个正则表达式从代码行中提取lambda。但我想这可能有点复杂。@cglacet我正在寻找一种通用的解决方案,用于处理任何类型的函数定义/函数指针/函数引用。看来lambda是更复杂的边缘情况。。。带有
def
的函数定义更简单。例如,如果我在一个列表中引用了一个“real”Python函数,类似于我在上面的示例中使用的
baz[2]
inspect
确实会提供函数的源代码,而不是列表的定义。上面的示例并没有给出定义列表的行,而是给出显示第2项的行
def foo(x, y):
    return x - y
bar = [1, 2, foo, 4]
print(inspect.getsource(bar[2]))