Call function without optional arguments if they are None

前端 未结 9 1993
自闭症患者
自闭症患者 2020-12-29 02:00

There\'s a function which takes optional arguments.

def alpha(p1=\"foo\", p2=\"bar\"):
     print(\'{0},{1}\'.format(p1, p2))

Let me iterat

相关标签:
9条回答
  • 2020-12-29 02:09

    Unfortunately, there's no way to do what you want. Even widely adopted python libraries/frameworks use your first approach. It's an extra line of code, but it is quite readable.

    Do not use the alpha("FOO", myp2 or "bar") approach, because, as you mention yourself, it creates a terrible kind of coupling, since it requires the caller to know details about the function.

    Regarding work-arounds: you could make a decorator for you function (using the inspect module), which checks the arguments passed to it. If one of them is None, it replaces the value with its own default value.

    0 讨论(0)
  • 2020-12-29 02:12

    although ** is definitely a language feature, it's surely not created for solving this particular problem. Your suggestion works, so does mine. Which one works better depends on the rest of the OP's code. However, there is still no way to write f(x or dont_pass_it_at_all) - blue_note

    Thanks to your great answers, I thought I'd try to do just that:

    # gen.py
    def callWithNonNoneArgs(f, *args, **kwargs):
        kwargsNotNone = {k: v for k, v in kwargs.items() if v is not None}
        return f(*args, **kwargsNotNone)
    

     

    # python interpreter
    >>> import gen
    >>> def alpha(p1="foo", p2="bar"):
    ...     print('{0},{1}'.format(p1,p2))
    ...
    >>> gen.callWithNonNoneArgs(alpha, p1="FOO", p2=None)
    FOO,bar
    >>> def beta(ree, p1="foo", p2="bar"):
    ...     print('{0},{1},{2}'.format(ree,p1,p2))
    ...
    >>> beta('hello', p2="world")
    hello,foo,world
    >>> beta('hello', p2=None)
    hello,foo,None
    >>> gen.callWithNonNoneArgs(beta, 'hello', p2=None)
    hello,foo,bar
    

    This is probably not perfect, but it seems to work: It's a function that you can call with another function and it's arguments, and it applies deceze's answer to filter out the arguments that are None.

    0 讨论(0)
  • 2020-12-29 02:13

    Pass the arguments as kwargs from a dictionary, from which you filter out the None values:

    kwargs = dict(p1='FOO', p2=None)
    
    alpha(**{k: v for k, v in kwargs.items() if v is not None})
    
    0 讨论(0)
  • 2020-12-29 02:19

    I had the same problem when calling some Swagger generated client code, which I couldn't modify, where None could end up in the query string if I didn't clean up the arguments before calling the generated methods. I ended up creating a simple helper function:

    def defined_kwargs(**kwargs):
        return {k: v for k, v in kwargs.items() if v is not None}
    
    >>> alpha(**defined_kwargs(p1="FOO", p2=None))
    FOO,bar
    

    It keeps things quite readable for more complex invocations:

    def beta(a, b, p1="foo", p2="bar"):
         print('{0},{1},{2},{3}'.format(a, b, p1, p2,))
    
    p1_value = "foo"
    p2_value = None
    
    >>> beta("hello",
             "world",
             **defined_kwargs(
                 p1=p1_value, 
                 p2=p2_value))
    
    hello,world,FOO,bar
    
    0 讨论(0)
  • 2020-12-29 02:21

    You could inspect the default values via alpha.__defaults__ and then use them instead of None. That way you circumvent the hard-coding of default values:

    >>> args = [None]
    >>> alpha('FOO', *[x if x is not None else y for x, y in zip(args, alpha.__defaults__[1:])])
    
    0 讨论(0)
  • 2020-12-29 02:28

    I'm surprised nobody brought this up

    def f(p1="foo", p2=None):
        p2 = "bar" if p2 is None else p2
        print(p1+p2)
    

    You assign None to p2 as standart (or don't, but this way you have the true standart at one point in your code) and use an inline if. Imo the most pythonic answer. Another thing that comes to mind is using a wrapper, but that would be way less readable.

    EDIT: What I'd probably do is use a dummy as standart value and check for that. So something like this:

    class dummy():
        pass
    
    def alpha(p1="foo", p2=dummy()):
        if isinstance(p2, dummy):
            p2 = "bar"
        print("{0},{1}".format(p1, p2))
    
    alpha()
    alpha("a","b")
    alpha(p2=None)
    

    produces:

    foo,bar
    a,b
    foo,None
    
    0 讨论(0)
提交回复
热议问题