0

I want to have a function that allows you to set a default return value instead of an error if the result it None. This gives me a function like the following:

def get_name(default=None):
    result = get_setting('name')
    if result:
        return result
    elif default:
        return default
    else:
        raise NoNameError

However, this causes a bug when the default value IS None. How whould I write this so that someone could call get_name(default=None) and get None back as opposed to an error?

I know I could do a hack such as:

def get_name(default=SomeSingletonObject):
    result = get_setting('name')
    if result:
        return result
    elif default is not SomeSingletonObject:
        return default
    else:
        raise NoNameError

But that is just bad form altogether

Nick Humrich
  • 14,905
  • 8
  • 62
  • 85
  • possible duplicate of [python - returning a default value](http://stackoverflow.com/questions/12265695/python-returning-a-default-value) – Jason S Aug 07 '14 at 23:52
  • Why are you throwing an error in the first place? – Blender Aug 08 '14 at 00:08
  • I would say something like `def get_name(default=type)` (or whatever the user is unlikely to pass) is practical enough for your purpose. – nodakai Aug 08 '14 at 00:26
  • So you're basically saying any value for default is acceptable, right? In that case the else branch should never execute so why can't you just make default the else branch and remove the NoNameError condition? – anderspitman Aug 08 '14 at 00:55
  • Why do you consider using some special unique object a hack? Isn't that what that `None` is after all -- and it's built into the language. – martineau Aug 08 '14 at 01:50
  • I would like to know what kind of cases you have where you actually want to raise an error like that. I can't come up with any uses cases myself to see where this is useful, but given the answer, it looks like something people actually do... – MxLDevs Aug 08 '14 at 03:26
  • @anders If I call `get_name()` without a parameter, I should get back an error if name doesn't exist. This is a common pattern, and in my use case, receiving an error is the true expected behaviour. (Plus its more pythonic) – Nick Humrich Aug 08 '14 at 15:59
  • 1
    @MxyL The use case is that not having a name means that the object isn't set up yet, which should throw an error. However, a more rare use just wants to know what it is IF it exists, so it doesn't need an error. – Nick Humrich Aug 08 '14 at 16:02
  • @Blender because I want to; it fits my purposes well. – Nick Humrich Aug 08 '14 at 16:02

1 Answers1

3

This is a common pattern used where None is perfectly acceptable input:

_marker = object()

def foo(val1=_marker):
    if val1 is _marker:
        do_some_stuff()

Here is a more useful example from the more-itertools library:

def first(iterable, default=_marker):
    try:
        return next(iter(iterable))
    except StopIteration:
        if default is _marker:
            raise ValueError('first() was called on an empty iterable...')
    return default
martineau
  • 119,623
  • 25
  • 170
  • 301
kylieCatt
  • 10,672
  • 5
  • 43
  • 51