Python dictionary switch 遍历其他函数,而不仅仅是调用的函数

Python dictionary switch goes through other functions instead of just the one called

我正在制作一个极其简单的计算器风格的应用程序,其中使用 5 个参数调用控制函数。第一个是设置计算器模式的字符串,另外 4 个是正在使用的数字。我用字典来方便各种模式的切换。

但是,应用程序似乎正在使用数字检查所有功能,而不是仅检查我想要的功能。例如,如果我另外使用负数,则会在平方根函数中出现数学域错误(显然不能使用负数)。使用正常的正数没有问题。

感谢您提供有关发生这种情况的原因以及解决方法的任何帮助或信息。

这是我的原始代码:

import math

def control(a, x, y, z, k):
    return {
        'ADDITION': addition(x, y),
        'SUBTRACTION': subtraction(x, y),
        'MULTIPLICATION': multiplication(x, y),
        'DIVISION': division(x, y),
        'MOD': modulo(x, y),
        'SECONDPOWER': secondPower(x),
        'POWER': power(x, y),
        'SECONDRADIX': secondRadix(x),
        'MAGIC': magic(x, y, z, k)
    }[a]

def addition(x, y):
    return float(x) + float(y)

def subtraction(x, y):
    return float(x) - float(y)

def multiplication(x, y):
    return float(x) * float(y)

def division(x, y):
    return float(x) / float(y)

def modulo(x, y):
    return float(x) % float(y)

def secondPower(x):
    return math.pow(float(x),2.0)

def power(x, y):
    return math.pow(float(x),float(y))

def secondRadix(x):
    return math.sqrt(float(x))

def magic(x, y, z, k):
    l = float(x) + float(k)
    m = float(y) + float(z)
    return (l / m) + 1.0

a = input()
x = input()
y = input()
z = input()
k = input()

try:
    control(a, x, y, z, k)
except ValueError:
    print("This operation is not supported for given input parameters")

out = control(a, x, y, z, k)
print(out)

这是日志:

C:\<path>\Python\Python35-32\python.exe C:/<path>/calculator.py
ADDITION
-6.0
5
3
2
This operation is not supported for given input parameters
Traceback (most recent call last):
  File "C:/<path>/calculator.py", line 67, in <module>
    out = control(a, x, y, z, k)
  File "C:/<path>/calculator.py", line 13, in control
    'SECONDRADIX': secondRadix(x),
  File "C:/<path>/calculator.py", line 47, in secondRadix
    return math.sqrt(float(x))
ValueError: math domain error

Process finished with exit code 1

当您将所有参数传递给 control 时,每个单独的函数都会被计算,因为您附加了括号。您最终尝试计算 math.sqrt(float(-6)) 这是一个虚数。为了避免这种情况,您必须使用通用 *args 设计控件,例如

def control(a, *args):
    return {
        'ADDITION': addition,
        'SUBTRACTION': subtraction,
        'MULTIPLICATION': multiplication,
        'DIVISION': division,
        'MOD': modulo,
        'SECONDPOWER': secondPower,
        'POWER': power,
        'SECONDRADIX': secondRadix,
        'MAGIC': magic
    }[a](*args)

它允许您检索您感兴趣的一个函数,然后用您的参数调用它。

您需要延迟评估您的功能:

from functools import partial

def control(a, x, y, z, k):
    return {
        'ADDITION':       partial(addition, x, y),
        'SUBTRACTION':    partial(subtraction, x, y),
        'MULTIPLICATION': partial(multiplication, x, y),
        'DIVISION':       partial(division, x, y),
        'MOD':            partial(modulo, x, y),
        'SECONDPOWER':    partial(secondPower, x),
        'POWER':          partial(power, x, y),
        'SECONDRADIX':    partial(secondRadix, x),
        'MAGIC':          partial(magic, x, y, z, k)
    }[a]()

在每次调用 control 时创建柯里化函数是低效的,所以这是第二种只创建一次字典的方法:

def control(a, x, y, z, k):
    return control.funcs[a](x, y, z, k)
control.funcs = {
    'ADDITION':       (lambda x, y, z, k: addition(x, y)),
    'SUBTRACTION':    (lambda x, y, z, k: subtraction(x, y)),
    'MULTIPLICATION': (lambda x, y, z, k: multiplication(x, y)),
    'DIVISION':       (lambda x, y, z, k: division(x, y)),
    'MOD':            (lambda x, y, z, k: modulo(x, y)),
    'SECONDPOWER':    (lambda x, y, z, k: secondPower(x)),
    'POWER':          (lambda x, y, z, k: power(x, y)),
    'SECONDRADIX':    (lambda x, y, z, k: secondRadix(x)),
    'MAGIC':          (lambda x, y, z, k: magic(x, y, z, k))
}

此时取消control函数,直接使用字典可能更简单。

最简单的方法就是重写代码,代码多了,但是维护起来更容易,你不会运行所有的方法,只有你想要的方法,因为看起来你是无论如何只是返回单个密钥。如果你想 运行 不止一个操作,然后将操作作为字符串传递,例如 a = input() --> "ADDITION SUBTRACTION",然后 split(" ") 来创建一个列表。遍历该列表并将 a 传递到方法控件中。

import math

def control(a, x, y, z, k):
    if a == 'ADDITION':
        return addition(x, y)
    elif a == 'SUBTRACTION':
        return subtraction(x, y)
    elif a == 'MULTIPLICATION':
        return multiplication(x, y)
    elif a == 'DIVISION':
        return division(x, y),
    elif a == 'MOD':
        return  modulo(x, y)
    elif a == 'SECONDPOWER':
        return secondPower(x)
    elif a == 'POWER':
        return power(x, y)
    elif a == 'SECONDRADIX':
        return secondRadix(x)
    elif a == 'MAGIC':
        return magic(x, y, z, k)

我不是 big 的忠实粉丝 if-elif-elif-else 但理解避免每次都构建字典的必要性。
扩展 @C.B. 的答案 - 您仍然可以使用字典调度机制,但只需将函数和参数数量存储在字典中。
现在可以在函数外部创建一次,例如:

dispatch = {
    'ADDITION': (addition, 2),
    'SUBTRACTION': (subtraction, 2),
    'MULTIPLICATION': (multiplication, 2),
    'DIVISION': (division, 2),
    'MOD': (modulo, 2),
    'SECONDPOWER': (secondPower, 1),
    'POWER': (power, 2),
    'SECONDRADIX': (secondRadix, 1),
    'MAGIC': (magic, 4)
}

def control(a, *args):
    func, count = dispatch[a] 
    return func(*args[:count])