Best way to ensure user calls methods in correct order?

Jugurtha Hadjar jugurtha.hadjar at gmail.com
Sat Jul 1 18:48:56 EDT 2017


A few questions: It looks to me you have a problem that looks a lot like
plant
processes where a process' output is another process' input.

Q1: Am I correct in describing your problem as follows?

input ---> |process a|---> |process b| ---> |process c| ---> output


Q2: Does every process change the type of its input to something not
produced
by other processes and not accepted by other processes? i.e: if the first
input is a list:

- Does |process a| accept a list and output a dict.
- Does |process b| accept a dict and output a tuple.
- Does |process c| accept a tuple and output a set.


You can do the following:

def pipeline(obj):
    mapping = {
        list: lambda: pipeline(a(obj)),
        dict: lambda: pipeline(b(obj)),
        tuple: lambda: c(obj),
    }
    return mapping[type(obj)]()


This way, calling process on a list will:
- Call a on it --> dict, then call pipeline on that dict which will:
- Call b on it --> tuple, then call pipeline on that tuple which will:
- Call c on it --> set, then will return that (last step).

You can also do it this way:

def pipeline(obj):
    mapping = {
        list: lambda: pipeline(a(obj)),
        dict: lambda: pipeline(b(obj)),
        tuple: lambda: pipeline(c(obj)),
        set: lambda: obj,
    }
    return mapping[type(obj)]()

However, if you call pipeline on the result of say, b (tuple).. Then it will
call c on that object, which gives a set, then call pipeline on that set,
which returns the set unchanged..

In other words, whatever the step your data is, calling pipeline on it will
automatically place it at the processing step.


This is for the first case.. If however you can't discriminate based on
type,
you can create your own "types" with custom classes or namedtuples.

If `a` accepts a list and outputs a list, and b accepts a list and outputs a
list, and c accepts a list and outputs a list...

You can just do:

class OutputA(list):
    """Result of a list processed by `a`."""

class OutputB(list):
    """Result of OutputA processed by `b`."""

class OutputC(list):
    """Result of OutputB processed by `c`."""


def pipeline(obj):
    mapping = {
        list: lambda: pipeline(a(obj)),
        OutputA: lambda: pipeline(b(obj)),
        OutputB: lambda: pipeline(c(obj)),
        OutputC: lambda: obj,
    }
    return mapping[type(obj)]()

You'll just have to change your functions like this:

def a(list_obj):
    ...
    _a_result = the_resulting_list_you_are_about_to_return
    return OutputA(_a_result)

def b(list_from_a):
    _b_result = also_a_list_you_were_returning
    return OutputB(_b_result)

def c(list_from_b):
    _c_result = you_get_the_point
    return OutputC(_c_result)






-- 
~Jugurtha Hadjar,



More information about the Python-list mailing list