Cómo crear una copia de una función de python

¿Existe la posibilidad de crear copias reales de las funciones de python? La opción más obvia fue http://docs.python.org/2/library/copy.html pero allí leí:

Realiza funciones y clases de “copia” (poco profundas y profundas), al devolver el objeto original sin cambios;

Necesito una copia real, porque podría cambiar algunos atributos de la función.

Actualizar:

Soy consciente de todas las posibilidades que se mencionan en los comentarios. Mi caso de uso se basa en la meta progtwigción donde construyo clases a partir de algunas especificaciones declarativas. Los detalles completos serían demasiado largos para SO, pero básicamente tengo una función como

    def do_something_usefull(self,arg): self.do_work() 

    Añadiré este método a varias clases. Estas clases pueden estar completamente sin relación. Usar clases de mezcla no es una opción: tendré muchas de estas funciones y terminaría agregando una clase base para cada función. Mi “solución alternativa” actual sería envolver esta función en una “fábrica” ​​como esta:

     def create_do_something(): def do_something_usefull(self,arg): self.do_work() 

    De esa manera siempre obtengo una nueva función do_something_useful, pero tengo que envolver todas mis funciones de esta manera.

    Puede confiar en mí, que soy consciente de que esta no es una progtwigción OO “normal”. Sé cómo resolver algo así “normalmente”. Pero este es un generador de código dynamic y me gustaría que todo sea lo más liviano y simple posible. ¿Y como las funciones de Python son objetos bastante normales, no creo que sea demasiado extraño preguntar cómo copiarlos?

    En 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 

    rendimientos

     (1, 2, 3, (5,), 4, 'BAR', 'BAZ') (1, 2, 3, (5,), 4, 'BAR', 'BAZ') [1, 2, 3] 

    En 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 

    rendimientos

     (1, 2) (1, 2) [1, 2, 3]