如何在Python中深拷贝一个函数?
我想在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"""