mercredi 29 juin 2016

Pythonic way to have a function return value in proper units

Objective: return a value from a function in the units (or any trivial modification) requested by the caller.

Background:

I am running Python 2.7 on a Raspberry Pi 3, and use the function distance() to get the distance a rotary encoder has turned. I need this distance in different units depending on where the function is called. How then, should this be written pythonically (i.e. short, and easily maintained).

First Attempt:

My first attempt was to use a unit of meters in the function, and have a long elif tree to select the right units to return in.

def distance(units='m'):
    my_distance = read_encoder()

    if units == 'm':
        return my_distance * 1.000
    elif units == 'km':
        return my_distance / 1000.
    elif units == 'cm':
        return my_distance * 10.00
    else:
        return -1

The nice thing about this approach is that it has a way to recognize a unit that isn't available.

Second Attempt:

My second attempt was to create a dictionary to contain various multipliers.

def distance(units='m'):
    multiplier = {
        'm': 1.000,
        'km': 0.001,
        'cm': 10.00
    }

    try:
        return read_encoder() * mulitplier[units]
    except KeyError:
        return -1

Here, unrecognized units are caught with a KeyError.

Relevance:

I know of existing libraries like Pint, but am looking for a solution to this programming problem. When you have a function in Python, and you need to make slight modifications to the output in a reusable way. I have other functions such as speed() that use 'm/s' as a base unit, and need a similar units argument. From my experience, a well-structured program does not involve a paragraph of elif branches before every return statement. In this case, if I wanted to change how I calculate the units, I would have to carefully grep through my code, and make sure I change how the units are calculated at every instance. A proper solution would only require changing the calculation once.

This is possibly too broad, but it is a pattern I keep running into.

Aucun commentaire:

Enregistrer un commentaire