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__)]