#python
#питон
Вопрос:
TL;DR почему eval
функция Python работает медленно?
Привет. Я решал упражнение по кодированию и заметил, что eval
функция вызывала тайм-ауты для некоторых тестовых случаев, и мне было интересно, почему это так, поскольку я не особенно помню, чтобы читал, что функция работает медленно.
Вот упражнение:
Вам дается список из n неотрицательных целых чисел и целевое целое число. Узнайте, сколько существует возможных способов добавить » » или » — » между указанными целыми числами, чтобы получить цель. Например, ввод
[1, 1, 1, 1, 1]
и3
будет возвращен5
, так как всего существует пять способов вставить или — для получения3
:-1 1 1 1 1
,1-1 1 1 1
,1 1-1 1 1
,1 1 1-1 1
,1 1 1 1-1
.
Решение, которое я изначально придумал, использовалось eval
следующим образом:
from itertools import product from typing import List def solution(numbers: List[int], target: int) -gt; int: numbers = [str(x) for x in numbers] length = len(numbers) all_operations = list(map(''.join, product(' -', repeat=length))) answer = 0 for operation in all_operations: eval_string = ''.join([''.join(x) for x in zip(operation, numbers)]) if eval(eval_string) == target: answer = 1 return answer
Второе решение, которое проходит все тестовые случаи, не использует eval
и просто выполняет арифметику шаг за шагом:
from itertools import product from typing import List def solution(numbers: List[int], target: int) -gt; int: numbers = [str(x) for x in numbers] length = len(numbers) all_signs = list(map(''.join, product(' -', repeat=length))) answer = 0 for operation in all_signs: value = 0 for op, number in zip(operation, numbers): if op == ' ': value = int(number) elif op == '-': value -= int(number) if value == target: answer = 1 return answer
Комментарии:
1.
eval
должен анализировать и интерпретировать заданную строку. Делать это медленнее, чем не делать этого.2. Вы сравниваете код, который уже скомпилирован (когда ваше приложение запущено), с кодом, который еще предстоит оценить во время выполнения — это сравнение яблок с бананами.
3. @MikeScotty Извините, но я не совсем понимаю; будет ли использование
eval
функции ссылаться на код, который должен быть оценен во время выполнения?4. В
eval
функции чтения кода, преобразовать его в байт-код во время выполнения, каждый раз в цикле.. а скрипт Python преобразует весь код в байт-код, как только перед казнью (это не компиляция кстати), во всяком случае, преобразование в байт-код-это ресурс, интенсивной эксплуатации, поэтому обычно это делается один раз до запуска кода.
Ответ №1:
Преобразование ваших значений в строки, а затем запуск eval не будет эффективным. Это будет быстрее, хотя, возможно, удастся улучшить это еще больше:
import itertools INTS = [1, 1, 1, 1, 1] CONST = 3 # build a new list comprised of the original INTS plus their negative values P = list(map(lambda x: -x, INTS)) INTS # work out the unique permutations s = set(itertools.permutations(P, len(INTS))) # iterate over (map) each unique permutations to see if its sum matches CONST print(list(map(lambda x: sum(x) == CONST, s)).count(True))