[python]python动态调用模块内的类或方法
需求
写py程序时候总是碰到下面这种场景,动态生成对象或者函数:
>>> def foo(): print "foo" >>> def bar(): print "bar" >>> func_list = ["foo","bar"] >>> for func in func_list: func() TypeError: 'str' object is not callable
这种需要根据字符串生成对象或者方法的需求,再java里大概是反射的一个功能,因为老是用到,所以在这里总结一下.
一共有以下几种方式:
eval
>>> for func in func_list: eval(func)() foo bar
eval是最简单粗暴的方式,会将字符串重新解释为可运行对象,也即是所有的可执行的字符串都会被编译为python对象然后执行结果.这种方式虽然能够得到正确的结果,但是一旦在某些程序中使用,便可能会给黑客入侵带来便利,因为可以动态执行所有的字符串,那么关于系统相关信息的函数也并不例外.eval is evil,除非十分必要,否则应该极力避免.
locals()和globals()
>>> for func in func_list: locals()[func]() foo bar >>> for func in func_list: globals()[func]() foo bar
locals()和globals()分别是存储python程序变量的两个dict,每个dict中都存放着不同数目的name[str]和value[object]的条目,其中lacals中存储的是局部变量,globas中存储的是全局变量.
使用这两个dict有一定限制,在单文件中尚可,但如果在多个包,尤其是每个包中有相同名字的对象或方法时,就有点力不从心了.
熟悉程序运行过程的朋友知道,程序在内存中分为不同的区,有着不同的空间和生命周期.其空间意义及周期如下:
Local:局部命名空间,每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、内部定义的局部变量。
Global:全局命名空间,每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、类、其他导入的模块、模块级的变量与常量。
Built-in:python自带的内建命名空间,任何模块均可以访问,放着内置的函数和异常。
Local(局部命名空间)在函数被调用时才被创建,但函数返回结果或抛出异常时被删除。(每一个递归函数都拥有自己的命名空间)。
Global(全局命名空间)在模块被加载时创建,通常一直保留直到python解释器退出。
Built-in(内建命名空间)在python解释器启动时创建,一直保留直到解释器退出。
各命名空间创建顺序:python解释器启动 ->创建内建命名空间 -> 加载模块 -> 创建全局命名空间 ->函数被调用 ->创建局部命名空间
各命名空间销毁顺序:函数调用结束 -> 销毁函数对应的局部命名空间 -> python虚拟机(解释器)退出 ->销毁全局命名空间 ->销毁内建命名空间
python解释器加载阶段会创建出内建命名空间、模块的全局命名空间,局部命名空间是在运行阶段函数被调用时动态创建出来的,函数调用结束动态的销毁的。
getattr()
>>> class Foo: def do_foo(self): ... def do_bar(self): ... >>> f = getattr(foo_instance, 'do_' + opname) >>> f()
多用于类属性方法的获取,当然包似乎也行.
methodcaller
>>> class Foo: def do_foo(self): print 1 def do_bar(self): print 2 >>> f = Foo() >>> from operator import methodcaller >>> methodcaller('do_foo')(f)
有点类似于getattr,不过getattr可以获取属性,methodcaller侧重于执行method.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~