3

I have a set of functions in python that gets the same 2 parameters + other parameters.

def myMethodA (param1, param2, specificParm)
    do code

 def myMethodB (param1, param2, specificParm1 specificParam2)
    do code

I waned to create a decorator that replace the need to call with the first 2 parameters by pushing the parameters before calling the function:

@withParams()
def myMethodA (specificParam)
        do code

But if I omit the parameters then the decorator can't call it either and if I leave them then the caller need to specify them as well.

anyway to solve this? Can I do something with args* but still have named parameters for specificParam? Also, How can I reference param1 and param2 inside myMethodA

1
  • Take a look at functools.partial too Commented Jul 30, 2017 at 19:36

4 Answers 4

1

It sounds like you may want functools.partial. It returns a new function with some parameters already specified:

import functools

def withParams(func):
    return functools.partial(func,1,2)

@withParams
def myMethodA (param1, param2, specificParam):
    print(param1,param2,specificParam)

@withParams
def myMethodB (param1, param2, specificParam1, specificParam2):
    print(param1,param2,specificParam1, specificParam2)

myMethodA(10)
myMethodB(12,13)
1 2 10
1 2 12 13
Sign up to request clarification or add additional context in comments.

4 Comments

This looks great but how does myMethodA(10) works if the signature is myMethodA (param1, param2, specificParam)?
Both options solve the problem and both can be used. I picked the partial since the syntax is cleaner
That's what a decorator does. Assigns a new function object to the function name. In this case the new function takes two fewer arguments and calls the original function with the two provided parameters plus any additional.
@EranWitkon Anyway, I think Marktolonen answer is a great fit. +1
0

You can add those two parameters when you call the function in the decorator's wrapper function as part of the kwargs. All decorated functions will automatically have those two parameters passed as keyword arguments before making the call:

def withParams(func):
    def wrapper(*args, **kwargs):
        kwargs['param1'] = 1
        kwargs['param2'] = 2
        return func(*args, **kwargs)
    return wrapper

@withParams
def add(specificparam, *args, **kwargs):
      print(specificparam)  # 3
      print(args)           # (4,)
      print(kwargs)         # {'param2': 2, 'param1': 1}
      return specificparam + sum(args) + sum(kwargs.values())

print(add(3,4)) # 10

You can drop the args part if all you'll be passing from the main function call are the specific parameters for each function.

7 Comments

This what I was hopping but isn't decorator just a function call? How would adding two parameters to a function that doesn;t expect them would work? I would expect to get something like ' method expected 1 parameter but 3 supplied
Also, in this way, I can not reference param1 and param2 in myMethodA as they are not defined.
@EranWitkon You could use *args in your function to collect param2 and param2 with the other arguments. See update.
Yes, this is good but I wanted to still have the specific params with explicit names. def add(spesificParm1 spesificParam2, *args, **kwargs):
@EranWitkon If you update your question with these requirements, I can improve the answer to fit them :)
|
0

I'd recommend you go old school, and just reassign the names using functools.partial:

# module foo

def func1(common_1, common_2, specific_1):
    pass

def func2(common_1, common_2, specific_2, specific_3):
    pass

Then elsewhere (or lower in the file, if you like) you can do this:

import functools

import foo

common_args = (1, 'fred')
foo.func1 = functools.partial(foo.func1, *common_args)
foo.func2 = functools.partial(foo.func2, *common_args)

# ...

foo.func1('special')

foo.func2('equally special', 'but different')

Comments

0

Sounds like you need functools.partial, to pre-populate the "constant" parameters:

>>> from functools import partial

>>> def myMethodA(param1, param2, specificParm):
        print("myMethodA(", param1, param2, specificParm, ")")

>>>> def myMethodB (param1, param2, specificParm1, specificParam2):
        print("myMethodB(", param1, param2, specificParm1, specificParam2, ")")

>>> preMethodA = partial(myMethodA, "p1", "p2")
>>> preMethodB = partial(myMethodB, "p1", "p2")
>>> preMethodA(34)
myMethodA( p1 p2 34 )
>>> preMethodB(8, 9)
myMethodB( p1 p2 8 9 )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.