python—获取当前模块中所有函数的列表。检查当前模块是否不工作?

python—获取当前模块中所有函数的列表。检查当前模块是否不工作?,python,Python,我有以下代码 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

我有以下代码

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/testfunctions不可能的原因。函数定义在Python中执行。函数只有在其定义被执行后才存在。只有在定义函数之后才能定义
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*
这很好:

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*
在这种情况下,
testfunctions
在调用
testall
之前不会进行求值,因此到那时这里没有问题,所有顶级模块代码(包括
test1
定义)都已求值,因此
testfunctions
将获得所有顶级函数。(我在这里假设,如果模块底部的块名,或者另一个脚本正在执行
导入测试;tests.test1(10)
,或者类似的操作,则从
调用
testall
test1
。)

事实上,即使您显式地命名了
test1
test2
,也不会有问题:

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文件)。编译器不需要知道名称有什么值,只需要知道它是本地的还是全局的(或者是一个闭包单元),而且它已经可以判断出
sys
inspect
test1
是全局的(因为您没有在
testall
或在一个封闭的范围内为它们赋值)

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

稍后,当您调用
testall
函数时,解释器将执行该函数。这是在列表理解(在第一个版本中)或全局名称查找(在第二个版本中)发生时。由于已对
test1
test2
的函数定义进行了评估,并将其绑定到模块中的全局名称,因此一切正常

如果您稍后调用
test1
,它调用
testall
,会怎么样?没问题。解释器执行
test1
,它调用了
testall
,这显然已经定义好了,因此解释器调用了它,其余部分与上一段相同

那么,如果在
test1
test2
定义之间调用
testall
test1
,会怎么样?在这种情况下,
test2
尚未定义,因此它不会出现在列表中(第一个版本),或者会引发
NameError
(第二个版本)。但只要你不这样做,就没有问题。没有什么好的理由这么做


如果您担心每次调用
testall
时计算
testfunctions
的可怕性能成本……首先,这是一个愚蠢的担忧;你打算给它打多少次电话?你的函数真的那么快,以至于调用和过滤
getmembers
的时间都出现在雷达上了吗?但如果真的有问题,只需使用您最喜欢的方式(可变默认值、privat全局、函数属性等)缓存值即可:

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

要排除任何导入的函数,请执行以下操作:

import sys
import inspect 
   [obj for name,obj in inspect.getmembers(sys.modules[__name__]) 
                         if (inspect.isfunction(obj) and 
                             name.startswith('test') and
                             obj.__module__ == __name__)]

通过导入和检查当前模块,从另一个设置fset的模块获取它如何?根据OP实际尝试的操作,只需在顶部定义一个
fset
函数,然后在需要值时调用该函数就足够了。然后,只要他在定义所有其他函数之前不调用该函数,一切都会很好。(除了他可能想在理解的末尾添加
和name!=“fset”
。它已经超过100个字符了,那么屏幕边缘还有15个字符吗?@ato:如果另一个模块导入当前模块,(a)它将在当前模块中执行代码,这意味着循环导入,以及(b)在执行整个当前模块之前,该值仍然不可用。@kindall:顺便说一下,解释得很好。我可能会用半页的篇幅讲述编译器和其他不相关的东西,并用两行文字说明您所涵盖的内容:@kindall:正如你所注意到的,为了回答OP的编辑,我最后讲了半页关于编译器的内容。:)也许您可以更清楚、简洁地回答后续问题。为什么不让fset作为一个返回列表的函数。\ux。您实际上为什么需要这个呢?尤其是,为什么需要在顶部定义它?@abarnert看起来我可以在底部定义testfunctions。但我认为testall不能使用它,因为它之前没有定义。@ato:
test1
必须在使用它时定义,这是在调用
testall
时,而不是在定义它时。如果你想了解技术细节,我可以在回答中解释。
import sys
import inspect 
   [obj for name,obj in inspect.getmembers(sys.modules[__name__]) 
                         if (inspect.isfunction(obj) and 
                             name.startswith('test') and
                             obj.__module__ == __name__)]