import sys
from types import FunctionType, MethodType
class aMeta(type):
def __new__(cls,name,bases,dct):
attr={
"__test_func__":FunctionType(cls.testFunc.__code__,cls.testFunc.__globals__,"__test_func__",cls.testFunc.__defaults__,cls.testFunc.__closure__),
"__test_method__": MethodType(cls.testFunc,cls),
"__test_dynamic_method__": MethodType(FunctionType(cls.testFunc.__code__,cls.testFunc.__globals__,"__test_func__",cls.testFunc.__defaults__,cls.testFunc.__closure__),cls)
}
for k,v in dct.items():
if k not in attr:
attr[k]=v
return super(aMeta,cls).__new__(cls,name,bases,attr)
def testFunc(self):
print(sys._getframe().f_code.co_name)
class aTestCls(metaclass=aMeta):
def __init__(self):
super().__init__()
if __name__ == "__main__":
t= aTestCls()
t.__test_func__()
t.__test_method__()
t.__test_dynamic_method__()
print(t.__test_func__.__func__.__name__)
print(t.__test_method__.__func__.__name__)
print(t.__test_dynamic_method__.__func__.__name__)
从输出来看:
t.__test_func__()
t.__test_method__()
t.__test_dynamic_method__()
输出为:testFunc
print(t.__test_func__.__func__.__name__)
print(t.__test_method__.__func__.__name__)
print(t.__test_dynamic_method__.__func__.__name__)
分别输出:
__test_func__
test_func
__test_func__
从实际运行结果来看:
FunctionType:是以testFunc为蓝本动态创建了一个函数,但是testFunc的CodeType没有做任何改变,也就是说co_name还是testFunc; 而FunctionType的name参数仅是改变了对象实例的__name__; 这也就造成了t.__test_func(),t.__test_method__,t.__test_dynamic_method__()的调用输出还是testFunc;
MethodType:仅是一个method-wapper;
如果需要动态创建函数,并在函数执行过程中获取函数本身的名称可以考虑以下两个方案:
1、通过定义一个FunctionOverride类,本类实现初始化保存__name__,并重写__call__方法; 在meta里实例化对应对象;
2、通过ast动态生成函数:
2.1 不通过sys._getframe().f_code.co_name获取方法名:
在函数本身内部定义一个__name__常量,保存函数本身名称,那么在函数内部可以通过调用__name__获取函数本身名称;
2.2 通过sys._getframe().f_code.co_name获取方法名
(以上两种方案本人均已代码验证过可行性;有兴趣的朋友可以自行按方案实现相关代码,在此就不写太多了)