简体   繁体   中英

How to pass arguments to a function inside a dictionary?

As switch case is not available in Python, I made use of dictionary for this to perform arithmetic operation:

a = 10
b = 5

def add(a, b):
    return a + b 

def sub(a, b):
    return a - b

def mul(a, b):
    return a * b

def div(a, b):
    return a / b

def default():
    return "not a valid option"

opt = {
   1: add,
   2: sub,
   3: mul,
   4: div
}

op = 2

def getdetails(op):
    return opt.get(op, default)()

getdetails(op)

How do I pass my a and b value to my function when I enter option which hits the dictionary to call particular function?

Tou should change:

def default():
    return "not a valid option"

def getdetails(op):
    return opt.get(op,default)()

getdetails(op)

To

def default(*_):
    return "not a valid option"

def getdetails(op):
    return opt.get(op, default)

res = getdetails(op)(a,b)

And it will work.

Full code example:

a = 10
b = 5


def add(a, b):
    return a + b


def sub(a, b):
    return a - b


def mul(a, b):
    return a * b


def div(a, b):
    return a / b


def default(*_):
    return "not a valid option"


opt = {
    1: add,
    2: sub,
    3: mul,
    4: div
}


def getdetails(op):
    return opt.get(op, default)


op = 2

res = getdetails(op)(a,b)

print(res)

Since Python 3.10 , there actually is a "switch-case" feature, called pattern matching :

a = 10
b = 5

op = 2

match op:
    case 1:
        print(a + b)
    case 2:
        print(a - b)
    case 3:
        print(a * b)
    case 4:
        print(a / b)
    case _:
        print("not a valid option")

The last case, _ , is a wildcard .


For earlier versions you can easily "emulate" something similar to a switch-case:

a = 10
b = 5

op = 2

def case(value):
    return op == value

if case(1):
    print(a + b)
elif case(2):
    print(a - b)
elif case(3):
    print(a * b)
elif case(4):
    print(a / b)
else:
    print("not a valid option")

Or, for keeping with your approach, I would do some small changes to your code:

  • No need to implement all those functions - there is the operator module for that.
  • I wouldn't even bother with a default function - as others mentioned, the different signature will cause you headaches ahead.
  • Instead, I would go for forgiveness instead of permission and assume the op exists, and if there is a KeyError - we know it is the default.
  • Finally, your actual mistake is that you simply didn't pass the arguments - opt.get(op, default)() should simply be opt.get(op, default)(a, b) , apart from the problem mentioned above with default .
from operator import add, sub, mul, truediv

a = 10
b = 5

opt = {
   1: add,
   2: sub,
   3: mul,
   4: truediv
}

op = 2

try:
    print(opt[op](a, b))
except KeyError:
    print("not a valid option")

Your code looks ok to me, but I made a change in your default function, so that there is no error when op is not available in your dictionary. Also add the function call:

a=10
b=5

def add(a,b):
    return a+b 

def sub(a,b):
    return a-b

def mul(a,b):
    return a*b

def div(a,b):
    return a/b

def default(*args): # a, b are input, to prevent an positional arguments error add *args.
    return "not a valid option"

opt={
   1: add,
   2: sub,
   3: mul,
   4: div
}

op=2
# Call the function:
print(opt.get(op, default)(a,b))
>>> 5
print( opt.get(None, default)(a,b) )
>>> 'not a valid option'

EDIT:

Why the *args part in the function? *args is one method to capture variable for a function which are not defiend:

def test(*args):
    for arg in args:
        print(arg, end=' ') # end=' ' adds an space instead of a new line after print.

test(1, 2, 5)
>>> 1, 2, 3

What happens when a function is called without *args ?:

def test():
    print('TEST')

test(1, 2)
>>> TypeError: test() takes 0 positional arguments but 2 were given

You are expecting a function from your dictionary and you are going to add the arguments a and b . Therefore you have to deal with them in each function in the dictionary.

What you also could do is:

def default(a,b):
    # Just ignore a,b
    return 'not valid'

That will also work, but if you want to add more arguments for other functions in the future the advantage of *args is taht it can take as much arguments as you want, there is no maximum.

Two ways you can do this:

Firstly, you can send the right away before the function is returned by sending it to getdetails() like so:

def getdetails(op, a, b):
    return opt.get(op)(a,b)

getdetails(op)

OR you could save the function the call it like so:

def getdetails(op):
    return opt.get(op)

getdetails(op)(a,b)

Considering that default is a special case, I would handle it manually instead of with get :

# instead of baking your own, use stdlib
from operator import add, sub, mul, div, mod

opt = {
   '+': add,
   '-': sub,
   '*': mul,
   '/': div,
   '%': mod,
}

def getresult(op, a, b):
    try:
        return opt[op](a, b)
    except KeyError:
        return default()

getresult('*', 10, 5)

If you do want to use get , you have to normalize the signature of default to accept the same arguments as the other options:

def default(*args, **kwargs):
    return 'Invalid option'

def getresult(op, a, b):
    return opt.get(op)(a, b)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM