Python Forum

Full Version: [split] Creating a variable as a function
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
Hi,

I knew dict could be used to replace "select... case"... statements, the single biggest thing i missed in Python.
So with the info of post #5, i tried to make something, but it's not quite allright. What is wrong? I get an extra 'None' in the output.
Output:
This has plenty of useful applications, e.g. the pythonic way to create a menu/switch statement, using dict with functions as values.
def AAA():
    print('AAAxxx')

def BBB():
    print('BBByyy')

def CCC():
    print('CCCzzz')

aaa = AAA
bbb = BBB
ccc = CCC

myDict = {100:aaa,200:bbb,300:ccc}
x = myDict[200]()
print(x)
Can i do without line 15 ?
Paul
(Sep-06-2020, 06:55 AM)DPaul Wrote: [ -> ]I get an extra 'None' in the output.

Of course you do. On line 15, you assign the return value of the function to x. The function referred to by bbb (and in fact this is true for all your functions) has no return statement, therefore implicitly returns None to its caller.
(Sep-06-2020, 07:04 AM)ndc85430 Wrote: [ -> ]
(Sep-06-2020, 06:55 AM)DPaul Wrote: [ -> ]I get an extra 'None' in the output.

Of course you do. On line 15, you assign the return value of the function to x. The function referred to by bbb (and in fact this is true for all your functions) has no return statement, therefore implicitly returns None to its caller.
OK, is this "perfect" then ? :-)
def AAA():
    return 'AAAxxx'

def BBB():
    return 'BBByyy'

def CCC():
    return 'CCCzzz'

aaa = AAA
bbb = BBB
ccc = CCC

myDict = {100:aaa,200:bbb,300:ccc}

x = myDict[200]()
print(x)
Paul
Your example is quite contrived, but in general, this is better design yes. In a real example, these functions would do more complex things and separating the concern of printing from what their main job is would make them more reusable, easier to test and maintain.
(Sep-06-2020, 07:24 AM)ndc85430 Wrote: [ -> ]In a real example, these functions would do more complex things and separating the concern of printing from what their main job is would make them more reusable, easier to test and maintain.
Agreed.

This is a step closer to "select..." statements of old. Smile

What i am still missing is "select" equivalents for:

x is between a and b.. do function...
x is between c and d ... do function...
or even,
x is a,b,c or d ... do function ....
x is w,z,t or v ... do function ...

Any thoughts on that?

paul
Besides cascading if statements?
import random

def fnA():
    return 'A'

def fnB():
    return 'B'

def fnC():
    return 'C'

selector = random.random()
if selector < 0.333 :
    print(fnA())
elif selector >= 0.333 and selector < 0.7 :
    print(fnB())
else :
    print(fnC())
(Sep-06-2020, 11:52 AM)jefsummers Wrote: [ -> ]Besides cascading if statements?

Cascading if statements have always been a possibility, since times immemorial, if you have just a couple of "cases".
But if you need 10, 50 or more, it becomes (very) cumbesome.

I've looked into this, and as long as a dict key MUST be a single item, dicts are not a solution.
I've seen some propose a tuple range as key, but it does not produce the goods.

It seems strange that python does not provide some direct construct for those very common "cases".

Paul
you can do something like this
def spam():
    return 'spam'

def eggs():
    return 'eggs'

# option 1: expand the keys
menu = {('a', 'b', 'c'):spam, ('x', 'y', 'z'):eggs}
menu = {key:value for item, value in menu.items() for key in item}
print(menu['a']())
print(menu['z']())

# option 2: define helper function
menu = {('a', 'b', 'c'):spam, ('x', 'y', 'z'):eggs}
def lookup_in(lookup_key, menu):
    for key, value in menu.items():
        if lookup_key in key:
            return value
print(lookup_in('a', menu)())
OK, I had seen attempts to do a tuple 'range' as key, post #8 proposes a kind of tuple 'list'.
In the old days we called this a "workaround". :-)

So we have a select...case solution with dictionaries for:
- Individual keys, the most direct solution (post # 3)
- tuple lists (post # 8)

Still one down : the "between" or "range" case.

Thanks,
Paul
(Sep-06-2020, 02:22 PM)DPaul Wrote: [ -> ]Still one down : the "between" or "range" case.
it will be the same workaround like the tuple
def spam():
    return 'spam'
 
def eggs():
    return 'eggs'

menu = {(2, 5):spam, (8, 10):eggs}
def lookup(lookup_key, menu):
    for (start, end), value in menu.items():
        if start <= lookup_key <= end:
            return value
print(lookup(9, menu)())
Here the tricky part is handling overlapping keys

(Sep-06-2020, 02:22 PM)DPaul Wrote: [ -> ]a kind of tuple 'list'.
no, it's not kind of tuple list, it's a tuple
Pages: 1 2 3