Оценка Python:Что не так с этим кодом?
-
12-09-2019 - |
Вопрос
Я пытаюсь написать очень простую утилиту Python для личного использования, которая подсчитывает количество строк в текстовом файле, для которых истинен предикат, указанный в командной строке.Вот код:
import sys
pred = sys.argv[2]
if sys.argv[1] == "stdin" :
handle = sys.stdin
else :
handle = open(sys.argv[1])
result = 0
for line in handle :
eval('result += 1 if ' + pred + ' else 0')
print result
Когда я запускаю его, используя python count.py myFile.txt "int(line) == 0"
, я получаю следующую ошибку:
File "c:/pycode/count.py", line 10, in <module>
eval('toAdd = 1 if ' + pred + ' else 0')
File "<string>", line 1
toAdd = 1 if int(line) == 0 else 0
Для меня это выглядит совершенно корректным кодом Python (хотя я никогда раньше не использовал eval Python, поэтому не знаю, в чем его особенности, если таковые имеются).Подскажите, пожалуйста, как это исправить, чтобы все заработало.
Решение
#!/usr/bin/env python
import fileinput, sys
pred = eval('lambda line: ' + sys.argv[1])
print sum(1 for line in fileinput.input(sys.argv[2:]) if pred(line))
Использование: pywc.py predicate [FILE]...
Выведите количество строк, удовлетворяющих predicate
для данного FILE
(с).
Без FILE
, или, когда FILE равен -, читать стандартный ввод.
Другие советы
Попробуйте использовать exec вместо eval.Разница между двумя объяснена здесь
пытаться:
for line in handle:
result += 1 if eval(pred) else 0
Функция python eval() оценивает выражения, а не операторы.Попробуйте заменить строку eval() на:
result += eval(pred + " else 0")
Действительно, вы ищете функцию компиляции:
>> a = compile("toAdd = 1 if int('0') == 0 else 0", 'tmp2.py', 'exec')
>>> eval(a)
>>> toAdd
1
eval предназначен только для выражений...компилировать при компиляции последовательность операторов в кодовый блок, который затем можно оценить.