python - returning a default value

I'm looking to mimic the behavior of built-in functions (like getattr) that allow the user to specify a "default" return value. My initial attempt was to do this

def myfunc(foo, default=None):
    # do stuff
    if (default is not None):
        return default
    raise SomeException()

The problem is that if the users wants None to be their return value, this function would instead raise an exception. second attempt:

def myfunc(foo, **kwargs):
    # do stuff
    if ('default' in kwargs):
        return kwargs['default']
    raise SomeException()

This addresses the above issue and allows the user to specify any arbitrary value, but introduces an annoyance in that the user must always specify default=bar in their function calls; they can't just provide bar at the end. Likewise, *args could be used, but prevents users from using default=bar if they prefer that syntax.

Combining *args and **kwargs provides a workable solution, but it feels like this is going to a lot of effort. It also potentially masks improper function calls (eg bar = myfunc(foo, baz, default=qux))

def myfunc(foo, *args, **kwargs):
    # do stuff
    if (len(args) == 1):
        return args[0]
    if ('default' in kwargs):
        return kwargs['default']
    raise SomeException()

Is there a simpler solution? (python 3.2 if that matters)


Solution 1:

You need to use a sentinel to detect that a default value was not set:

sentinel = object()

def func(someparam, default=sentinel):
    if default is not sentinel:
        print("You passed in something else!")

This works because an instance of object() will always have it's own memory id and thus is will only return True if the exact value was left in place. Any other value will not register as the same object, including None.

You'll see different variants of the above trick in various different python projects. Any of the following sentinels would also work:

sentinel = []
sentinel = {}