pythonnonetype

Python idiom for applying a function only when value is not None


A function is receiving a number of values that are all strings but need to be parsed in various ways, e.g.

vote_count = int(input_1)
score = float(input_2)
person = Person(input_3)

This is all fine except the inputs can also be None and in this case, instead of parsing the values I would like to end up with None assigned to the left hand side. This can be done with

vote_count = int(input_1) if input_1 is not None else None
...

but this seems much less readable especially with many repeated lines like this one. I'm considering defining a function that simplifies this, something like

def whendefined(func, value):
    return func(value) if value is not None else None

which could be used like

vote_count = whendefined(int, input_1)
...

My question is, is there a common idiom for this? Possibly using built-in Python functions? Even if not, is there a commonly used name for a function like this?


Solution

  • In other languages there's Option typing, which is a bit different (solves the problem with a type system), but has the same motivation (what do do about nulls).

    In Python there's more of a focus on runtime detection of this kind of thing, so you can wrap the function with an None-detecting guard (rather the data which is what Option typing does).

    You could write a decorator that only executes a function if the argument is not None:

    def option(function):
        def wrapper(*args, **kwargs):
            if len(args) > 0 and args[0] is not None:
              return function(*args, **kwargs)
        return wrapper
    

    You should probably adapt that third line to be more suitable to the kind of data you're working with.

    In use:

    @option
    def optionprint(inp):
        return inp + "!!"
    
    >>> optionprint(None)
    # Nothing
    
    >>> optionprint("hello")
    'hello!!'
    

    and with a return value

    @option
    def optioninc(input):
        return input + 1
    
    >>> optioninc(None)
    >>> # Nothing
    
    >>> optioninc(100)
    101
    

    or wrap a type-constructing function

    >>> int_or_none = option(int)
    >>> int_or_none(None)
    # Nothing
    >>> int_or_none(12)
    12