gpt4 book ai didi

python - 获取当前模块中所有函数的列表。检查当前模块不起作用?

转载 作者:太空狗 更新时间:2023-10-29 17:56:50 25 4
gpt4 key购买 nike

我有以下代码

fset = [ obj for name,obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj) ]

def func(num):
pass

if __name__ == "__main__":
print(fset)

打印

[]

然而这

def func(num):
pass

fset = [ obj for name,obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj) ]

if __name__ == "__main__":
print(fset)

打印

[<function func at 0x7f35c29383b0>]

那么 fset 如何成为当前模块中所有函数的列表,其中 fset 定义在所有函数的顶部?

编辑 1:我想做的是

def testall(arg):
return any(f(arg) for f in testfunctions)

def test1(arg):
#code here
# may call testall but wont call anyother test*

def test2(arg):
#code here
# may call testall but wont call anyother test*

以后可能会增加更多的测试功能。这就是 fset/testfunctions 的原因

最佳答案

EDIT 1: What I am trying to do is

def testall(arg):
return any(f(arg) for f in testfunctions)

def test1(arg):
#code here
# may call testall but wont call anyother test*

这很好用:

def testall(arg):
testfunctions = [obj for name,obj in inspect.getmembers(sys.modules[__name__])
if (inspect.isfunction(obj) and
name.startwith('test') and name != 'testall')]
return any(f(arg) for f in testfunctions)

def test1(arg):
#code here
# may call testall but wont call anyother test*

在这种情况下,testfunctionstestall 被调用之前不会被评估,所以这里没有问题——到那时,所有顶级模块代码(包括test1 definition) 将被评估,因此 testfunctions 将获得所有顶级函数。 (我在这里假设 testalltest1 是从模块底部的 if __name__ == '__main__' block 调用的,或者另一个脚本正在执行 import tests; tests.test1(10),或者类似的东西。)

事实上,即使你明确命名了test1test2,也不会有问题:

def testall(arg):
testfunctions = ('test1',)
return any(f(arg) for f in testfunctions)

def test1(arg):
#code here
# may call testall but wont call anyother test*

同样,test1 已在您调用 testall 时定义,因此一切正常。


如果您想了解其工作原理,则必须了解此处的各个阶段。

当您导入模块或运行顶层脚本时,第一个阶段是编译(除非已经有缓存的 .pyc 文件)。编译器不需要知道一个名字有什么值(value),只需要知道它是本地的还是全局的(或闭包单元),它已经可以告诉 sysinspecttest1 是全局变量(因为您没有在 testall 或封闭范围内分配给它们)。

接下来,解释器按顺序执行顶层模块的编译字节码。这包括执行函数定义。所以,testall 变成了一个函数,然后 test1 变成了一个函数,然后 test2 变成了一个函数。 (函数实际上只是适当的编译代码,附加了一些额外的东西,比如定义它的全局命名空间。)

稍后,当您调用testall 函数时,解释器会执行该函数。这是列表理解(在第一个版本中)或全局名称查找(在第二个版本中)发生的时候。由于 test1test2 的函数定义已经被评估并绑定(bind)到模块中的全局名称,所以一切正常。

如果您稍后调用 test1,而后者调用 testall,会怎样?没问题。解释器执行test1,其中有对testall的调用,显然已经定义好了,所以解释器调用那个,其余同上一段。

那么,如果您在 test1test2 定义之间调用 testalltest1 会怎么样?在那种情况下,test2 还没有被定义,因此它不会出现在列表中(第一个版本),或者会引发一个 NameError(第二个版本)。但只要你不那样做,就没有问题。并且没有充分的理由这样做。


如果您担心每次调用 testall 时计算 testfunctions 的可怕性能成本……好吧,首先,这是一个愚蠢的担心;你要调用多少次?您的函数真的快到调用和过滤 getmembers 的时间甚至出现在雷达上吗?但如果真的很担心,只需将值缓存在您最喜欢的常用方式中——可变默认值、私有(private)全局函数、函数属性……:

def testall(arg, _functions_cache=[]):
if not _functions_cache:
_functions_cache.extend([…])

关于python - 获取当前模块中所有函数的列表。检查当前模块不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18907712/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com