在 Python 2.7.3 中,eval() 函数可以用来执行字符串形式的 Python 表达式,并返回表达式的值。这是一个在进行数学计算时非常有用的功能,尤其是当你需要处理由用户输入的或动态生成的表达式时。然而,使用 eval() 时需要特别小心,因为它也可以执行任意代码,可能导致安全问题。

这里是一个简单的例子,展示如何使用 eval() 来计算数学表达式,并且介绍如何安全地限制 eval() 所执行代码的环境。

Python 2.7.3中使用eval和list来求解数学表达式_字符串

1、问题背景

在 Python 2.7.3 中,我需要创建一个函数来进行以下操作:

  • 创建一个数学问题并将其作为字符串输出,其中主题是运算顺序。
  • 作为输出的第二部分,输出此问题的正确答案。
  • 作为其余输出,输出错误答案,但如果更改运算顺序(例如让减法先于乘法),则可以达到这些答案。

该函数不需要任何参数,但在问题过程中需要我们进行以下导入:

import random
from random import choice

这样做是为了生成随机整数作为任何问题的数字,并选择问题中涉及的操作,例如 *,/,+,-。

2、解决方案

有两种解决这个问题的方法:

方法一

  1. 我通过交替将整数和操作添加到字符串来制作一个字符串(因此以整数结尾),然后在最后在字符串的某些位置加上括号。
  2. 我使用 eval() 来评估字符串并因此提供正确的答案。
  3. 我通过在不同的地方插入括号来制作该字符串的其他版本,以便返回不同的答案,然后我使用 eval() 对其进行求值以找到其他答案。

方法二

这类似于方法一,但将元素放入列表中。

  1. 将运算顺序提供为列表作为输入,例如正确的运算顺序为 [*,(,/),(+,-)],然后找到这些运算在列表中的位置,并对左右的整数执行运算,删除列表的 3 个部分,并用我们找到的答案替换它们。我们对整个列表的所有操作执行此操作,使用重复。
  2. 我通过输入一个运算顺序方面不同的列表来简单地获得不同的答案,从而使寻找错误答案的步骤变得更容易。

代码例子

方法一

import random
from random import choice

def create_question():
  """Creates a math question as a string."""

  # Generate random integers and operations.
  integers = [random.randint(1, 10) for _ in range(5)]
  operations = choice(['+', '-', '*', '/'])

  # Create a string representation of the question.
  question = ""
  for i in range(len(integers)):
    question += str(integers[i])
    if i < len(integers) - 1:
      question += operations

  # Add parentheses to the string in random places.
  for _ in range(random.randint(1, 3)):
    index = random.randint(0, len(question) - 1)
    question = question[:index] + '(' + question[index:]

  return question

def evaluate_question(question):
  """Evaluates a math question string and returns the answer."""

  return eval(question)

def find_incorrect_answers(question):
  """Finds incorrect answers to a math question string."""

  incorrect_answers = []

  # Try adding parentheses to the string in different places.
  for i in range(len(question)):
    if question[i] in ['+', '-', '*', '/']:
      new_question = question[:i] + '(' + question[i:] + ')'
      incorrect_answers.append(evaluate_question(new_question))

  # Try changing the order of operations.
  for operation in ['+', '-', '*', '/']:
    new_question = question.replace(operation, '')
    incorrect_answers.append(evaluate_question(new_question))

  return incorrect_answers

# Test the function.
question = create_question()
print("Question:", question)
correct_answer = evaluate_question(question)
print("Correct answer:", correct_answer)
incorrect_answers = find_incorrect_answers(question)
print("Incorrect answers:", incorrect_answers)

方法二

import random
from random import choice

def create_question():
  """Creates a math question as a string."""

  # Generate random integers and operations.
  integers = [random.randint(1, 10) for _ in range(5)]
  operations = choice(['+', '-', '*', '/'])

  # Create a list representation of the question.
  question = []
  for i in range(len(integers)):
    question.append(integers[i])
    if i < len(integers) - 1:
      question.append(operations)

  return question

def evaluate_question(question):
  """Evaluates a math question list and returns the answer."""

  # Find the indices of the operations.
  operation_indices = [i for i, op in enumerate(question) if op in ['+', '-', '*', '/']]

  # Evaluate the question using the correct order of operations.
  while operation_indices:
    # Find the index of the first operation.
    index = operation_indices[0]

    # Perform the operation.
    operation = question[index]
    left_operand = question[index - 1]
    right_operand = question[index + 1]
    result = eval(str(left_operand) + operation + str(right_operand))

    # Replace the operation and its operands with the result.
    question = question[:index - 1] + [result] + question[index + 2:]

    # Update the list of operation indices.
    operation_indices = [i - 1 for i in operation_indices if i > index]

  # Return the final result.
  return question[0]

def find_incorrect_answers(question):
  """Finds incorrect answers to a math question list."""

  incorrect_answers = []

  # Try changing the order of operations.
  for operation in ['+', '-', '*', '/']:
    new_question = question.copy()

    # Find the indices of the operations.
    operation_indices = [i for i, op in enumerate(new_question) if op in ['+', '-', '*', '/']]

    # Change the order of operations.
    while operation_indices:
      # Find the index of the first operation.
      index = operation_indices[0]

      # Perform the operation.
      operation = new_question[index]
      left_operand = new_question[index - 1]
      right_operand = new_question[index + 1]
      result = eval(str(left_operand) + operation + str(right_operand))

      # Replace the operation and its operands with the result.
      new_question = new_question[:index - 1] + [result] + new_question[index + 2:]

      # Update the list of operation indices.
      operation_indices = [i - 1 for i in operation_indices if i > index]

    # Evaluate the question.
    incorrect_answers.append(evaluate_question(new_question))

  return incorrect_answers

# Test the function.
question = create_question()
print("Question:", question)
correct_answer = evaluate_question(question)
print("Correct answer:", correct_answer)
incorrect_answers = find_incorrect_answers(question)
print("Incorrect answers:", incorrect_answers)

虽然 eval() 是一个强大的工具,能够动态执行字符串形式的代码,但它的使用需要谨慎,尤其是在处理用户输入的数据时。确保限制 eval() 的执行环境可以帮助防止潜在的安全风险。此外,对于复杂的数学表达式解析和计算,考虑使用像 NumPy 或 SymPy 这样的专门库,这些库提供了更强大、更安全的数学运算支持。