-1

lets say a I have two functions:

def foo1(bar, a, b, c):
  result = bar(a, b)
  return result

def foo2(bar, a, b, c):
  result = bar(a, b, c)
  return result

the arguments are the same in both situation, but it depends on the function "bar" that may need only 2, and another one may need all 3 (in the same order)

is it possible to make this into a single function without knowing how many arguments the referenced function needs?

dima kal
  • 29
  • 1
  • 10
  • Do you want to pass all supplied arguments into the function? Or leave off the extras? – Draconis Mar 05 '19 at 22:22
  • 2
    Possible duplicate of [How can I find the number of arguments of a Python function?](https://stackoverflow.com/questions/847936/how-can-i-find-the-number-of-arguments-of-a-python-function) – pault Mar 05 '19 at 22:23
  • Another option is to use `try: bar(a, b, c) except TypeError: bar(a, b)` – pault Mar 05 '19 at 22:23
  • I don't want to pass all arguments. try/except would work, but is there another way around? – dima kal Mar 05 '19 at 22:25
  • @dimakal there are a number of methods on the duplicate I linked. – pault Mar 05 '19 at 22:33

4 Answers4

1

You can use the function object's __code__.co_argcount attribute to obtain the number of arguments it expects, with which you can slice the argument list:

def bar1(a, b):
    return b, a

def bar2(a, b, c):
    return c, b, a

def foo(bar, *args):
    return bar(*args[:bar.__code__.co_argcount])

print(foo(bar1, 1, 2, 3))
print(foo(bar2, 1, 2, 3))

This outputs:

(2, 1)
(3, 2, 1)
blhsing
  • 91,368
  • 6
  • 71
  • 106
  • which is more "pythonic"/faster? __code__.co_argcount or signature? I assume because I don't have to import anything that this would be a better solution? – dima kal Mar 05 '19 at 22:39
0

I think you may be looking for the * expansion operator

def foo(bar, *args):
  result = bar(*args)
  return result

For example:

In [1]: def foo(bar,*args): 
   ...:     return bar(*args) 
   ...:                                                                                                                                      

In [2]: def f1(a): 
   ...:     return a 
   ...:                                                                                                                                      

In [3]: def f2(a,b): 
   ...:     return a+b 
   ...:                                                                                                                                      

In [4]: foo(f1,5)                                                                                                                            
Out[4]: 5

In [5]: foo(f2,5,6)                                                                                                                          
Out[5]: 11

In [6]: foo(f1,5,6)                                                                                                                          
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-5ca26cac7f4d> in <module>
----> 1 foo(f1,5,6)

<ipython-input-1-fe8d4699f744> in foo(bar, *args)
      1 def foo(bar,*args):
----> 2     return bar(*args)
      3 

TypeError: f1() takes 1 positional argument but 2 were given
knap
  • 11
  • 2
0

Yes. If I understand you correctly, you want to pass unspecified amount of arguments to a function?

If so, you can accept a tuple; such that the function can accept (a, b, c) or several more arguments. Tuples are similar to lists, but are not mutable. Of course, it's up to you to make sure the right amount of arguments are inputted.

Below, arguments is a tuple. You can do len(arguments) to find out how many arguments were inputted.

arguments=(bar, a, b)
foo(arguments)

def foo(my_tuple):
  result = arguments[0](arguments[1], arguments[2])
  return result
Eduardo Morales
  • 764
  • 7
  • 29
0

Try this.

from inspect import signature

def foo(bar, *args):
    arg_count = len(signature(bar).parameters)
    return bar(*args[:arg_count])

This passes however many arguments the function expects, and ignores the rest. If you want to use all the arguments later, they're in the args list.

Draconis
  • 3,209
  • 1
  • 19
  • 31