Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a copy of a python function [duplicate]

Is there a possibility to create real copies of python functions? The most obvious choice was http://docs.python.org/2/library/copy.html but there I read:

It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged;

I need a real copy, because I might change some attributes of the function.

Update:

I'm aware of all the possibilities which are mentioned in the comments. My use case is based on meta programming where I construct classes out of some declarative specifications. Complete details would be too long for SO, but basically I have a function like

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

I will add this method to various classes. Thoses classes can be completly unrelated. Using mixin classes is not an option: I will have many such functions and would end up adding a base class for each function. My current "workaround" would be to wrap this function in a "factory" like this:

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

That way I always get a new do_something_useful function, but I have to wrap all my functions like this.

You can trust me, that I'm aware, that this is no "normal" OO programming. I know how to solve something like that "normally". But this is a dynamic code generator and I would like to keep everything as lightweight and simple as possible. And as python functions are quite normal objects, I don't think it's too strange to ask how to copy them!?

like image 215
Achim Avatar asked Nov 21 '12 22:11

Achim


People also ask

How do you duplicate a function in Python?

The Python copy() method creates a copy of an existing list. The copy() method is added to the end of a list object and so it does not accept any parameters. copy() returns a new list.

Does copy () make a deep copy Python?

Shallow and deep copy in Python: copy(), deepcopy() In Python, you can make a shallow and deep copy with the copy() method of list , dictionary, etc., or the copy() and deepcopy() functions of the copy module.


1 Answers

In 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 

yields

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

In 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 

yields

(1, 2) (1, 2) [1, 2, 3] 
like image 76
unutbu Avatar answered Sep 21 '22 05:09

unutbu