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

Air*_*oon 12 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)
Run Code Online (Sandbox Code Playgroud)

版画

[]
Run Code Online (Sandbox Code Playgroud)

不过这个

def func(num):
    pass

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

if __name__ == "__main__":
    print(fset)
Run Code Online (Sandbox Code Playgroud)

版画

[<function func at 0x7f35c29383b0>]
Run Code Online (Sandbox Code Playgroud)

那么如何将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*
Run Code Online (Sandbox Code Playgroud)

将来可能会添加更多测试功能.这就是fset/testfunctions的原因

aba*_*ert 13

编辑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*    
Run Code Online (Sandbox Code Playgroud)

这很好用:

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*
Run Code Online (Sandbox Code Playgroud)

在这种情况下,testfunctions直到testall被调用才进行评估,因此这里没有问题 - 到那时,所有顶级模块代码(包括test1定义)都将被评估,因此testfunctions将获得所有顶级函数.(我假设在这里testall或test1正在从if __name__ == '__main__'模块底部的块中调用,或者其他脚本正在执行import tests; tests.test1(10),或类似的东西.)

事实上,即使你明确命名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*
Run Code Online (Sandbox Code Playgroud)

再次,test1已经定义了你打电话的时间testall,所以一切都很好.


如果您想了解其工作原理,您必须了解这里的各个阶段.

导入模块或运行顶级脚本时,第一个阶段是编译(除非已有缓存的.pyc文件).编译器并不需要知道一个名字有什么价值,只是无论是本地或全局(或闭合细胞),而且它已经可以告诉大家,sys并inspect和test1有全局(因为你不分配给他们testall或在封闭范围).

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

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

如果你以后打电话test1,打电话testall怎么办?没问题.解释器执行test1,它有一个调用testall,显然已经定义了,所以解释器调用它,其余部分与前一段相同.

那么,如果你在和定义之间testall或test1之间打电话怎么办?在这种情况下,尚未定义,因此它不会出现在列表(第一个版本)中,或者会引发(第二个版本).但只要你不这样做,就没有问题.并没有充分的理由这样做.test1test2test2NameError


如果你担心testfunctions每次打电话时计算的可怕性能成本testall......那么,首先,这是一个愚蠢的担忧; 你要打多少次电话?您的功能是否真的如此之快以至于调用和过滤的时间getmembers甚至会出现在雷达上?但是,如果真的是一个担心,只需将值缓存在您最喜欢的常用方法 - 可变默认值,privat全局,函数属性,......:

def testall(arg, _functions_cache=[]):
    if not _functions_cache:
        _functions_cache.extend([…])
Run Code Online (Sandbox Code Playgroud)


kin*_*all 11

它不可能.函数定义在Python 中执行.在执行定义之前,函数不存在.您的fset变量不能确定,直到被定义的功能后.

  • 根据OP实际尝试做的事情,仅在顶部定义一个`fset` _function_就足够了,然后只要他需要值就调用它.然后,只要他在定义所有其他函数之前没有调用函数,一切都会好的.(除非他可能想要在他的理解结束时加上`和名字!='fset'.它已经超过100个字符,所以又是超过屏幕边缘的15个?) (2认同)

Chr*_*ick 7

要排除任何导入的函数,此方法有效:

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__)]
Run Code Online (Sandbox Code Playgroud)