我有以下代码
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变量不能确定,直到被定义的功能后.
要排除任何导入的函数,此方法有效:
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)
| 归档时间: |
|
| 查看次数: |
7709 次 |
| 最近记录: |