How to check whether optional function parameter is set

前端 未结 10 1350
傲寒
傲寒 2020-12-02 15:06

Is there an easy way in Python to check whether the value of an optional parameter comes from its default value, or because the user has set it explicitly at the function ca

相关标签:
10条回答
  • 2020-12-02 15:42

    Not really. The standard way is to use a default value that the user would not be expected to pass, e.g. an object instance:

    DEFAULT = object()
    def foo(param=DEFAULT):
        if param is DEFAULT:
            ...
    

    Usually you can just use None as the default value, if it doesn't make sense as a value the user would want to pass.

    The alternative is to use kwargs:

    def foo(**kwargs):
        if 'param' in kwargs:
            param = kwargs['param']
        else:
            ...
    

    However this is overly verbose and makes your function more difficult to use as its documentation will not automatically include the param parameter.

    0 讨论(0)
  • 2020-12-02 15:44

    I sometimes use a universally unique string (like a UUID).

    import uuid
    DEFAULT = uuid.uuid4()
    def foo(arg=DEFAULT):
      if arg is DEFAULT:
        # it was not passed in
      else:
        # it was passed in
    

    This way, no user could even guess the default if they tried so I can be very confident that when I see that value for arg, it was not passed in.

    0 讨论(0)
  • 2020-12-02 15:44

    A little freakish approach would be:

    class CheckerFunction(object):
        def __init__(self, function, **defaults):
            self.function = function
            self.defaults = defaults
    
        def __call__(self, **kwargs):
            for key in self.defaults:
                if(key in kwargs):
                    if(kwargs[key] == self.defaults[key]):
                        print 'passed default'
                    else:
                        print 'passed different'
                else:
                    print 'not passed'
                    kwargs[key] = self.defaults[key]
    
            return self.function(**kwargs)
    
    def f(a):
        print a
    
    check_f = CheckerFunction(f, a='z')
    check_f(a='z')
    check_f(a='b')
    check_f()
    

    Which outputs:

    passed default
    z
    passed different
    b
    not passed
    z
    

    Now this, as I mentioned, is quite freakish, but it does the job. However this is quite unreadable and similarly to ecatmur's suggestion won't be automatically documented.

    0 讨论(0)
  • 2020-12-02 15:49

    The following function decorator, explicit_checker, makes a set of parameter names of all the parameters given explicitly. It adds the result as an extra parameter (explicit_params) to the function. Just do 'a' in explicit_params to check if parameter a is given explicitly.

    def explicit_checker(f):
        varnames = f.func_code.co_varnames
        def wrapper(*a, **kw):
            kw['explicit_params'] = set(list(varnames[:len(a)]) + kw.keys())
            return f(*a, **kw)
        return wrapper
    
    @explicit_checker
    def my_function(a, b=0, c=1, explicit_params=None):
        print a, b, c, explicit_params
        if 'b' in explicit_params:
            pass # Do whatever you want
    
    
    my_function(1)
    my_function(1, 0)
    my_function(1, c=1)
    
    0 讨论(0)
提交回复
热议问题