是否有可能创建python函数的真实副本?最明显的选择是http://docs.python.org/2/library/copy.html,但我读到了:
它通过“复制”功能和类(浅和深) 返回原始对象不变;
我需要一个真正的副本,因为我可能会更改该函数的某些属性。
更新
我知道评论中提到的所有可能性。我的用例基于元编程,我从一些声明性规范中构造类。完整的细节对于SO来说太长了,但基本上我有一个像
这样的功能def do_something_usefull(self,arg):
self.do_work()
我将把这个方法添加到各个类中。类可以完全不相关。使用mixin类不是一个选项:我将有许多这样的函数,并最终为每个函数添加一个基类。我目前的“解决方法”是将此函数包装在这样的“工厂”中:
def create_do_something():
def do_something_usefull(self,arg):
self.do_work()
这样我总是得到一个新的do_something_useful函数,但是我必须像这样包装所有函数。
我相信我,我知道,这不是“正常”的OO编程。我知道如何解决“通常”这样的问题。但这是一个动态代码生成器,我希望尽可能保持轻量级和简单的一切。而且由于python函数是非常普通的对象,我认为如何复制它们并不奇怪!?
答案 0 :(得分:30)
在 Python3 :
中import types
import functools
def copy_func(f):
"""Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
g = types.FunctionType(f.__code__, f.__globals__, name=f.__name__,
argdefs=f.__defaults__,
closure=f.__closure__)
g = functools.update_wrapper(g, f)
g.__kwdefaults__ = f.__kwdefaults__
return g
def f(arg1, arg2, arg3, kwarg1="FOO", *args, kwarg2="BAR", kwarg3="BAZ"):
return (arg1, arg2, arg3, args, kwarg1, kwarg2, kwarg3)
f.cache = [1,2,3]
g = copy_func(f)
print(f(1,2,3,4,5))
print(g(1,2,3,4,5))
print(g.cache)
assert f is not g
产量
(1, 2, 3, (5,), 4, 'BAR', 'BAZ')
(1, 2, 3, (5,), 4, 'BAR', 'BAZ')
[1, 2, 3]
在 Python2 :
中import types
import functools
def copy_func(f):
"""Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
g = types.FunctionType(f.func_code, f.func_globals, name=f.func_name,
argdefs=f.func_defaults,
closure=f.func_closure)
g = functools.update_wrapper(g, f)
return g
def f(x, y=2):
return x,y
f.cache = [1,2,3]
g = copy_func(f)
print(f(1))
print(g(1))
print(g.cache)
assert f is not g
产量
(1, 2)
(1, 2)
[1, 2, 3]