在Python中如何压缩这个if语句?

2024-06-23 19:36:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在用Python创建一个计算器,遇到了一个小问题:if-else语句中有28个条件:

if operation0 == "+" and operation1 == "+" and operation2 == "+": # First operation is addition
    print(number0 + number1 + number2 + number3)
elif operation0 == "+" and operation1 == "+" and operation2 == "*":
    print(number0 + number1 + number2 * number3)
elif operation0 == "+" and operation1 == "+" and operation2 == "^":
    print(number0 + number1 + number2 ** number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "+":
    print(number0 + number1 * number2 + number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "*":
    print(number0 + number1 * number2 * number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "^":
    print(number0 + number1 * number2 ** number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "+":
    print(number0 + number1 ** number2 + number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "*":
    print(number0 + number1 ** number2 * number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "^":
    print(number0 + number1 ** number2 ** number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "+": # First operation is multiplication
    print(number0 * number1 + number2 + number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "*":
    print(number0 * number1 + number2 * number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "^":
    print(number0 * number1 + number2 ** number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "+":
    print(number0 * number1 * number2 + number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "*":
    print(number0 * number1 * number2 * number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "^":
    print(number0 * number1 * number2 ** number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "+":
    print(number0 * number1 ** number2 + number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "*":
    print(number0 * number1 ** number2 * number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "^":
    print(number0 * number1 ** number2 ** number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "+": # First operation is exponentiation
    print(number0 ** number1 + number2 + number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "*":
    print(number0 ** number1 + number2 * number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "^":
    print(number0 ** number1 + number2 ** number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "+":
    print(number0 ** number1 * number2 + number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "*":
    print(number0 ** number1 * number2 * number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "^":
    print(number0 ** number1 * number2 ** number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "+":
    print(number0 ** number1 ** number2 + number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "*":
    print(number0 ** number1 ** number2 * number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "^":
    print(number0 ** number1 ** number2 ** number3)
else:
    print("Error")

我试过的东西都不管用,我在这个网站上也找不到任何东西来帮助我压缩代码。如此多的重复ELIF是不合理的,任何数量的减少都将被感激


Tags: andifisoperationelsefirstprintelif
3条回答

免责声明:解决方案可能会使用各种不相关的概念,无法在此处进行解释

要获得优先级,必须正确解析输入。有几种方法可以做到这一点;一个常见的是Dijkstra的shunting yard算法。
由于这只是一个示例,我们将放弃良好实践(错误处理、类)以获得更简洁的代码

首先,我们需要列出先例。更高的优先级意味着操作符具有更高的优先级,因此它执行得更早

precedences = {
    '^': 3,
    '*': 2, '/': 2,
    '+': 1, '-': 1
}

然后,我们需要将操作与每个操作符关联起来。为此,我们可以使用operator模块中的函数:

from operator import pow, truediv, mul, add, sub
do = {
    '^': pow,
    '*': mul, '/': truediv,
    '+': add, '-': sub
}

最后,我们需要实现决定何时计算表达式的逻辑。首先,我们比操作多了一个数字,所以我们将其放在堆栈上:

def shunt(numbers, operations):
    stack = [numbers.pop(0)]
    operators = []

然后,我们处理每个运算符对

    while len(numbers):
        operator = operations.pop(0)
        precedence = precedences[operator]

当一个操作的优先级(执行时间早于当前操作)高于当前操作时(使用do字典)对其求值。我们从堆栈中删除左操作数和右操作数,并从do中查找适当的函数以计算结果:

        while operators and precedences[operators[-1]] >= precedence:
            [left, right], stack[-2:] = stack[-2:], []
            stack.append(do[operators.pop()](left, right))

然后,我们将当前运算符和编号附加到堆栈:

        operators.append(operator)
        stack.append(numbers.pop(0))

所有数字和运算符用完后,我们评估其余的运算符,直到只剩下一个数字,然后返回:

    while len(stack) > 1:
        [left, right], stack[-2:] = stack[-2:], []
        stack.append(do[operators.pop()](left, right))
    return stack[0]

把它们放在一起(Try it online!):

from operator import pow, truediv, mul, add, sub

precedences = {
    '^': 3,
    '*': 2, '/': 2,
    '+': 1, '-': 1
}

do = {
    '^': pow,
    '*': mul, '/': truediv,
    '+': add, '-': sub
}

def shunt(numbers, operations):
    stack = [numbers.pop(0)]
    operators = []
    while len(numbers):
        operator = operations.pop(0)
        precedence = precedences[operator]
        while operators and precedences[operators[-1]] >= precedence:
            [left, right], stack[-2:] = stack[-2:], []
            stack.append(do[operators.pop()](left, right))
        operators.append(operator)
        stack.append(numbers.pop(0))
    while len(stack) > 1:
        [left, right], stack[-2:] = stack[-2:], []
        stack.append(do[operators.pop()](left, right))
    return stack[0]

在对多个值执行公共处理时,应使用列表而不是单个变量。这允许您将通用逻辑应用于元素,并基于可存储在变量中的索引对其进行操作:

def compute(*operNums):
    operNums   = list(operNums)
    numbers    = operNums[::2]  # [number0,number1,number2,number3]
    operations = operNums[1::2] # [operation0,operation1,operation2]
    while operations:           # process list until all operations performed
        for op in ("^","**","*","+"):          # find highest priority operation
            if op not in operations: continue
            i = operations.index(op)           # index of operation
            operations.pop(i)                  # remove completed operation
            if   op in ["^","**"]: numbers[i] **= numbers.pop(i+1) # remove right side
            elif op == "*":        numbers[i]  *= numbers.pop(i+1) # left side number
            elif op == "+":        numbers[i]  += numbers.pop(i+1) # is replaced by result   
            else: return "ERROR"
    return numbers[0]

print(compute(1,"+",2,"**",3,"*",5)) # 41

操作顺序使这变得困难,但并非不可能:

# helper function to do an operation
def doop(num1, op, num2):
    if op == "^":
        return num1 ** num2
    if op == "+":
        return num1 + num2
    if op == "-":
        return num1 - num2
    if op == "*":
        return num1 * num2
    if op == "/":
        return num1 / num2
    # if we don't recognize the operation then error
    raise Exception("Invalid operation.")

# have a list of sets with operator precedence
precedence = [
    {"^"},
    {"*", "/"},
    {"+", "-"}
]

# hard coded values for testing
nums = [1, 2, 3, 4]
ops = ["+", "-", "*"]
# this represents 1 + 2 - 3 * 4

# start at highest to lowest precedence
for prec in precedence:
    # we have to use a while loop to have manual control of `i`
    i = 0
    while i < len(ops):
        # store the current operation
        op = ops[i]
        # if the operation isn't in the current precedence level we skip it
        if op in prec:
            # we can get rid of the operation to evaluate it
            ops.pop(i)
            # we can merge the two numbers around the operation into one
            # by performing the calculation
            nums[i:i + 2] = [doop(nums[i], op, nums[i + 1])]
            # we need to decrease i so we don't skip over the next operation
            i -= 1
        i += 1

if len(nums) != 1:
    raise Exception("Invalid operation count.")

print(nums[0]) # -9

相关问题 更多 >

    热门问题