如何创建python函数的副本

发布于 2021-01-29 19:16:11

是否有可能创建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
被浏览
52
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    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]
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看