如何在Python中深拷贝一个函数?

38 投票
9 回答
16787 浏览
提问于 2025-04-16 20:33

我想在Python中制作一个函数的深拷贝。根据文档copy模块并没有提供帮助,文档中提到:

这个模块无法复制像模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组或任何类似类型的东西。它确实可以“复制”函数和类(无论是浅拷贝还是深拷贝),但返回的仍然是原始对象,没有改变;这与pickle模块处理这些对象的方式是兼容的。

我的目标是有两个实现相同的函数,但它们的文档字符串(docstring)不同。

def A():
    """A"""
    pass

B = make_a_deepcopy_of(A)
B.__doc__ = """B"""

那么,这该怎么做呢?

9 个回答

8
from functools import partial

def a():
    """Returns 1"""
    return 1

b = partial(a)
b.__doc__ = """Returns 1, OR DOES IT!"""

print help(a)
print help(b)

把它包裹成一个部分吗?

30

我的目标是让两个函数有相同的实现,但文档字符串不同。

大多数用户会这样做,比如原始函数在 old_module.py 文件里:

def implementation(arg1, arg2): 
    """this is a killer function"""

而在 new_module.py 文件里:

from old_module import implementation as _implementation

def implementation(arg1, arg2):
    """a different docstring"""
    return _implementation(arg1, arg2)

这是重用功能最简单的方法,读起来也容易理解。

不过,也许你有很好的理由来问这个主要问题:

我怎么在Python中复制一个函数?

为了兼容Python 2和3,我建议使用函数的特殊 __dunder__ 属性。例如:

import types

def copy_func(f, name=None):
    '''
    return a function with same code, globals, defaults, closure, and 
    name (or provide a new name)
    '''
    fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
        f.__defaults__, f.__closure__)
    # in case f was given attrs (note this dict is a shallow copy):
    fn.__dict__.update(f.__dict__) 
    return fn

这里有一个使用示例:

def main():
    from logging import getLogger as _getLogger # pyflakes:ignore, must copy
    getLogger = copy_func(_getLogger)
    getLogger.__doc__ += '\n    This function is from the Std Lib logging module.\n    '
    assert getLogger.__doc__ is not _getLogger.__doc__
    assert getLogger.__doc__ != _getLogger.__doc__

有位评论者说:

这对内置函数是行不通的

其实我不会对内置函数这样做。对于用纯Python写的函数,我几乎没有理由这样做,我怀疑如果你这样做,可能是走了弯路(当然我也可能错)。

如果你想要一个函数,它的功能和内置函数一样,并且重用实现,就像复制一样,那你应该用另一个函数来包装这个函数,比如:

_sum = sum
def sum(iterable, start=0):
    """sum function that works like the regular sum function, but noisy"""
    print('calling the sum function')
    return _sum(iterable, start)
    
33

FunctionType构造函数用于对一个函数进行深拷贝,也就是创建这个函数的一个完整副本。

import types
def copy_func(f, name=None):
    return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
        f.func_defaults, f.func_closure)

def A():
    """A"""
    pass
B = copy_func(A, "B")
B.__doc__ = """B"""

撰写回答