0

I would like to copy an existing function from an existing module in the following way:

def foo(a,b,c=1,d=3,*arg):
   return True

myClass.foo = lambda b,c,d,*arg : foo(my_value_of_a, b,c,d,*arg)

However, there are several problems with this approach namely:

  • I am doing this in a loop and I don't know the arguments of most functions
  • I am losing the default values - which I absolutely cannot
  • The __docs__ and other attributes would be nice to keep too

I tried to do something like this:

handler = getattr(mod,'foo')
handler.__defaults__ = tuple([my_value_of_a] + list(handler.__defaults__))
myClass.foo = handler

which is almost enough for my use case (just because I always modify the first argument only). The problem is that if I call mod.foo() it also has my_value_of_a as the default value for a!

I tried using the copy module to do a handler=deepcopy(handler) but even that didn't work and modifying the default values of handler also modifies the default values of the module function itself.

Any suggestions on who to do this in a "pythonic" way? I probably cannot use decorators either, since I'm looping over functions from external modules (several, actually).

  • What you doing there is called monkey patching and considered bad practice. What is the actual problem you are trying to solve with this? – Klaus D. Jun 05 '20 at 14:04
  • What's the point exactly? You want to use function `foo` as a method on your class, passing one specific default parameter, but leaving the rest of the parameters behaving the same? – deceze Jun 05 '20 at 14:05
  • This is called [`currying`](https://en.wikipedia.org/wiki/Currying) look at functools.partial [https://docs.python.org/3/library/functools.html#functools.partial](https://docs.python.org/3/library/functools.html#functools.partial) – Alan Hoover Jun 05 '20 at 14:05
  • If I understood your question clearly, why don't you encapsulate your base function `foo` in a class, and then inherit this class in the other classes that will need this function? – Yasser Mohsen Jun 05 '20 at 14:09
  • Thanks for your reply! I'm trying to do exactly what is written above: to copy a series of functions from an external module while passing very specific arguments. The purpose is to have not to call ```modulename.submodulename.my_function_name(first_argument=myclass_name.my_attribute_name.value_a, b, c, d...)``` but simply ```myclass_name.my_function_name(b,c,d..)``` since the whole structure is very regular. – Benedict Holysword Jun 05 '20 at 14:11
  • Then you want [`partial`](https://docs.python.org/3/library/functools.html#functools.partial). Or perhaps `c = lambda *args, **kwargs: foo(my_arg, *args, **kwargs)`. – deceze Jun 05 '20 at 14:18
  • Is `my_value_of_a` a constant or is it (based on) an instance variable? – alani Jun 05 '20 at 14:56
  • Does this answer your question? [In Python, partial function application (currying) versus explicit function definition](https://stackoverflow.com/questions/5091528/in-python-partial-function-application-currying-versus-explicit-function-defi) – Alan Hoover Jun 05 '20 at 18:41

0 Answers0