Python 如何在运行时创建 class 的方法
Python How to create method of class in runtime
我很好奇如何在运行时为 class 创建自定义方法...
我的意思是例如从数据库读取的方法名称、参数名称、方法主体并将此方法分配给 class 或实例。
我发现可以添加已编写的方法:
class A:
def __init__(self):
pass
def method(self):
return True
A.method = method
a = A()
print(a.method())
但我有兴趣从头开始完全组装一种新方法:
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
# To create method from pieces
可以使用 __dict__
吗?或者如何做到这一点?
方法是对象的另一个属性,即class。它们可以像其他属性一样添加:
代码:
class A:
def __init__(self):
pass
def method(self):
return True
def another_method(self):
return False
setattr(A, 'another_method', another_method)
测试代码:
a = A()
print(a.another_method())
结果:
False
字符串中的方法:
添加如果你真的需要从数据库或类似的地方获取你的方法,你可以像这样使用exec:
method_string = """
def yet_another_method(self):
return type(self).__name__
"""
exec(method_string)
setattr(A, 'yet_another_method', yet_another_method)
a = A()
print(a.yet_another_method())
结果:
A
这个答案必须小心对待,使用 exec
或 eval
可以 运行 任意代码并可能危及您的系统。因此,如果您依靠用户输入来创建函数,您 绝不能使用此 !!!
抛开警告,您可以使用 exec
:
简单地创建任何内容
exec("""
def method():
return True
""")
>>> method()
True
所以您基本上需要的只是一种满足您的要求的方法:
functionname = 'funfunc'
parameters = ['a', 'b']
body = 'return a + b'
exec("""
def {functionname}({parameters}):
{body}
""".format(
functionname=functionname,
parameters=', '.join(parameters),
body='\n'.join([' {line}'.format(line=line) for line in body.split('\n')])))
正文将缩进,使其成为 有效的 语法,参数列表将是 joined
使用 ,
。和测试:
>>> funfunc(1, 2)
3
我发现的最佳解决方案之一如下:
def import_code(code, name, add_to_sys_modules=0):
"""
Import dynamically generated code as a module. code is the
object containing the code (a string, a file handle or an
actual compiled code object, same types as accepted by an
exec statement). The name is the name to give to the module,
and the final argument says wheter to add it to sys.modules
or not. If it is added, a subsequent import statement using
name will return this module. If it is not added to sys.modules
import will try to load it in the normal fashion.
import foo
is equivalent to
foofile = open("/path/to/foo.py")
foo = importCode(foofile,"foo",1)
Returns a newly generated module.
"""
import sys,imp
module = imp.new_module(name)
exec(code,module.__dict__)
if add_to_sys_modules:
sys.modules[name] = module
return module
class A:
def __init__(self):
pass
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
scratch = "def {0}({1}):\n\t{2}".format(name, ','.join(params), body)
new_module = import_code(scratch, "test")
A.method = new_module.method
a = A()
print(a.method())
原函数import_code由以下linkhttp://code.activestate.com/recipes/82234-importing-a-dynamically-generated-module/
使用此解决方案,我可以动态创建方法,在运行时加载它们并 link 到我想要的任何对象!!
我很好奇如何在运行时为 class 创建自定义方法...
我的意思是例如从数据库读取的方法名称、参数名称、方法主体并将此方法分配给 class 或实例。
我发现可以添加已编写的方法:
class A:
def __init__(self):
pass
def method(self):
return True
A.method = method
a = A()
print(a.method())
但我有兴趣从头开始完全组装一种新方法:
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
# To create method from pieces
可以使用 __dict__
吗?或者如何做到这一点?
方法是对象的另一个属性,即class。它们可以像其他属性一样添加:
代码:
class A:
def __init__(self):
pass
def method(self):
return True
def another_method(self):
return False
setattr(A, 'another_method', another_method)
测试代码:
a = A()
print(a.another_method())
结果:
False
字符串中的方法:
添加如果你真的需要从数据库或类似的地方获取你的方法,你可以像这样使用exec:
method_string = """
def yet_another_method(self):
return type(self).__name__
"""
exec(method_string)
setattr(A, 'yet_another_method', yet_another_method)
a = A()
print(a.yet_another_method())
结果:
A
这个答案必须小心对待,使用 exec
或 eval
可以 运行 任意代码并可能危及您的系统。因此,如果您依靠用户输入来创建函数,您 绝不能使用此 !!!
抛开警告,您可以使用 exec
:
exec("""
def method():
return True
""")
>>> method()
True
所以您基本上需要的只是一种满足您的要求的方法:
functionname = 'funfunc'
parameters = ['a', 'b']
body = 'return a + b'
exec("""
def {functionname}({parameters}):
{body}
""".format(
functionname=functionname,
parameters=', '.join(parameters),
body='\n'.join([' {line}'.format(line=line) for line in body.split('\n')])))
正文将缩进,使其成为 有效的 语法,参数列表将是 joined
使用 ,
。和测试:
>>> funfunc(1, 2)
3
我发现的最佳解决方案之一如下:
def import_code(code, name, add_to_sys_modules=0):
"""
Import dynamically generated code as a module. code is the
object containing the code (a string, a file handle or an
actual compiled code object, same types as accepted by an
exec statement). The name is the name to give to the module,
and the final argument says wheter to add it to sys.modules
or not. If it is added, a subsequent import statement using
name will return this module. If it is not added to sys.modules
import will try to load it in the normal fashion.
import foo
is equivalent to
foofile = open("/path/to/foo.py")
foo = importCode(foofile,"foo",1)
Returns a newly generated module.
"""
import sys,imp
module = imp.new_module(name)
exec(code,module.__dict__)
if add_to_sys_modules:
sys.modules[name] = module
return module
class A:
def __init__(self):
pass
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
scratch = "def {0}({1}):\n\t{2}".format(name, ','.join(params), body)
new_module = import_code(scratch, "test")
A.method = new_module.method
a = A()
print(a.method())
原函数import_code由以下linkhttp://code.activestate.com/recipes/82234-importing-a-dynamically-generated-module/
使用此解决方案,我可以动态创建方法,在运行时加载它们并 link 到我想要的任何对象!!