简体   繁体   中英

Pass arguments only when needed

As an example I have a function f and a variable a=1 . Sometimes f needs a and I want to call f(a=a) and other times f has no arguments. How can I deal with that?

When I try to call f(a=a) (expecting that it will silently ignore the case where a is not used in f ), I get the following TypeError:

f got an unexpected keyword argument 'a'

Edit

I want to implement a function g such that, given:

def f1(a):
    return a

def f2():
    return 1

we have:

g(f1, a) == a
g(f2, a) == 1

use keyword dictionary in f :

def f(**kwargs):
    if 'a' in kwargs:
        print("a passed with value {}".format(kwargs['a']))
    else:
        print('a not passed')

f(a=12)
f()

prints:

a passed with value 12
a not passed

it makes argument testing/retrieving completely manual. You can do anything you want, and it can be generalized to several arguments.

This also forbids to pass arguments as positional like f(12) which is probably a good thing in your case.

>>> f(12)
Traceback (most recent call last):
TypeError: f() takes 0 positional arguments but 1 was given

The drawback is that the caller cannot rely on parameter names to know what to pass. Either create a docstring, or people will have to read the code/guess...

Now to apply that to your edit, which kind of changes the problem I must say. So f2 cannot be changed, in that cas the work must be done in the wrapper function:

def f1(a):
    return a
def f2():
    return 1

def g(f,arg):
    try:
        return f(a=arg)
    except TypeError:
        return f()

a=12
print(g(f1, a))
print(g(f2, a))

prints:

12
1

so "better ask forgiveness than permission": if we get a TypeError (raised when the parameter isn't known by the function), we just call the function without the parameter. The drawback if that if the first function returns a TypeError , we cannot know if it was the parameters or inside the function.

A workaround would be to inspect the error message and only call the function without parameters if the error message is about parameters:

def g(f,arg):
    try:
        return f(a=arg)
    except TypeError as e:
        if "unexpected keyword" in str(e):
            return f()
        else:
            raise e  # another TypeError, let it pass

It seems you want to inspect a function's arguments.

For that, use the inspect module:

import inspect
def g(somefunc, *params):
    num_args = len(inspect.getargspec(somefunc).args)
    return somefunc(*params[:num_args])

Testing, with your functions:

def f1(a):
    return a

def f2():
    return 1

>>> print(g(f1, 3))
3
>>> print(g(f2, 3))
1

Simply specify the default argument in the function def line...

def f(a=1):
    return(a)
print(f()) #returns 1
print(f(a = 2)) #returns 2

For your next part (as you seemed to have switched your question with edits...

def g(f, a):
    return(f(a))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM