JPHamlett
JPHamlett

Reputation: 365

Declare function from within dictionary

def mainProgram(myDict):
    methodDict = {'add': addDB(myDict, params[1], params[2]),
                  'find': findDB(myDict, params[1]),
                  'del': removeDB(myDict, params[1], params[2]),
                  'clear': clearAll(myDict)}
    inpt = None
    while inpt != "End":
        inpt = input("-->")
        params = inpt.split()
        methodDict[params[0]]

Here is my code, when I try to execute the code I get, "UnboundLocalError: local variable 'params' referenced before assignment"

Is it possible to do what I am trying to do in python?

Upvotes: 2

Views: 106

Answers (4)

Adam Smith
Adam Smith

Reputation: 54163

Are you trying to compose a function using the arguments given to the command line to the input prompt? You can do that using lambda, though in this case you seem to already have functions defined, so why worry about it?

def main_program(dct):
    methods = {'add': addDB,
               'find': findDB,
               'del': removeDB,
               'clear': clearAll}

    inp = input("whatever")
    method_name, *args = inp.split()
    try:
        method = methods[method_name]
    except KeyError:
        # what do you do when the user's entry is wrong?
    else:
        method(dct, *args)

You can also use functools.partial with this approach, as @ozgur did in his excellent answer

from functools import partial

def main_program(dct):
    methods = {'add': partial(addDB, dct),
               ...}
    # note that this is identical in effect to
    # # lambda *args: addDB(dct, *args)
    ...
    method_name, *args = inp.split()
    method = methods[method_name]  # ignoring the try/catch behavior above
    method(*args)

Upvotes: 2

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52093

You can use functools.partial function to delay the execution of a function unless all parameters are provided.

from functools import partial

def add(x, y):
    return x + y

>>> partial_add = partial(add, 5)
>>> partial_add(7)
12

As for your question;

def mainProgram(myDict):
    methodDict = {'add': partial(addDB, myDict),
                  'find': partial(findDB, myDict),
                  'del': partial(removeDB, myDict),
                  'clear': partial(clearAll, myDict)}

    inpt = None
    while inpt != "End":
        inpt = input("-->")
        params = inpt.split()
        methodDict[params[0]](*params[1:])

Upvotes: 4

Laszlowaty
Laszlowaty

Reputation: 1323

This isn't exactly solution, but i think it's better to use reference than declare inside dictionary.

def test():
    print("it works")

dict = {"blabla" : test}
dict["blabla"]()

Upvotes: 1

Tasos Vogiatzoglou
Tasos Vogiatzoglou

Reputation: 2453

So, what actually happens at

 methodDict = {'add': addDB(myDict, params[1], params[2]),
              'find': findDB(myDict, params[1]),
              'del': removeDB(myDict, params[1], params[2]),
              'clear': clearAll(myDict)}

is that you execute addDB etc, that is, your methodDict would contain the result of addDB(...params...) if it were to run.

Unfortunately it does not run, as params is not defined when that execution happens.

What you'd want to do is, store a callable in the dictionary and run it... something like

methodDict = {'add': lambda x: addDB(myDict, x[0], x[1])}
# and you execute with
methodDict['add'](params)

Upvotes: 6

Related Questions