Marco Herrarte
Marco Herrarte

Reputation: 1620

Select a function in a Pythonic way

Suppose I have the following vars:

x
y

and functions:

def runx(x):
    print(x)

def runy(y):
    print (y)

def runxy(x, y):
    print(x + y)

def nonexy():
    print('none')

What's the Pythonic way to choose a function based on the next requirements:

-If value is only greater than y run the func runy

-If value is only greater than x run the func runx

-If value is greater than both x and y run the func runxy

-If value is not greather than x and y runt the func nonexy

value, x, y could be any number

Example:

x = 4
y = 6
value = 5

Here value is only greater than x, so run runx(x)

Upvotes: 0

Views: 132

Answers (6)

danbal
danbal

Reputation: 1531

We define a dictionary, which maps a boolean-pair to a lambda expression.
The boolean-pair is a two-tuple, representing the function-selecting criteria.
The lambda expression wraps a function. It takes x y, and calls the function with the parameters it needs.

Now, we can define a function which combines the tools we defined above.

mapping = {
    (True, True): lambda x,y: runxy(x,y),
    (True, False): lambda x,y: runx(x),
    (False, True): lambda x,y: runy(y),
    (False, False): lambda x,y: nonexy()
}

def f(x, y, value):
    mapping[value > x, value > y](x,y)


Note that it is enough to define mapping only once, regardless how many times we want to run the task. This is why we put it outside f. (No need to define it each time the task is run.)

Upvotes: 1

chapelo
chapelo

Reputation: 2562

If all the functions take x,y as parameters, you could use:

(nonexy,runx,runy,runxy)[1*(x<=value<=y)+2*(y<=value<=x)+3*(x<value>y)](x,y)

Upvotes: 1

m.wasowski
m.wasowski

Reputation: 6386

Even more overkill than other answers, but might be interesting for someone:

def fn_picker(value, x, y):
    functions = { # lambdas to make it shorter
        0: lambda kwargs: 'none',
        1: lambda kwargs: kwargs['x'],
        2: lambda kwargs: kwargs['y'],
        3: lambda kwargs: kwargs['x'] + kwargs['y']
    }
    key = sum([(value > x), (value > y)*2]) # True is 1, False is 0
    fn = functions[key]
    return fn(locals())

print(fn_picker(5, 4, 6))

Upvotes: 2

cassandracomar
cassandracomar

Reputation: 1519

if value > y and value <= x:
    runy(y)
elif value <= y and value > x:
    runx(x)
elif value > x and value > y:
    runxy(x, y)
else:
    nonexy()

There's no real good way to handle this kind of pattern but to just write out the if/else block.

Upvotes: 3

user2864740
user2864740

Reputation: 61935

One approach that is often forgotten is the use of logic tables. Now, while I'm not arguing that this is the best approach here, I consider it interesting so here goes - take or leave what you will.

             value > y   value <= y
             ----------  ----------
value > x  | runxy       runx
value <= x | runy        nonex

Then we can codify it as so, utilizing the fact that functions are first-class values:

arr = [[runxy, runx], [runy, nonex]]

And access it as so:

col = 0 if value > y else 1
row = 0 if value > x else 1
fn = arr[row][col]

Then just edit the current design such all the functions should take x and y parameters (or use wrapping lambdas in the above table) and..

fn(x, y)

Upvotes: 6

Mark
Mark

Reputation: 3277

if value > y :
    if value > x :
        runxy(x, y)
    else :
        runy(y)
else :
    if value > x :
        runx(x)
    else :
        nonexy()

Am I missing something?

Upvotes: 7

Related Questions