В дополнение к другим отличным ответам я хотел бы добавить, как git rebase -i
всегда путает меня с порядком фиксации - от старого до более нового или наоборот? Итак, это мой рабочий процесс:
git rebase -i HEAD~[N]
, где N - число коммитов, которые я хочу присоединиться, , начиная с самого последнего . Таким образом, git rebase -i HEAD~5
будет означать «squash последние 5 коммитов в новый»; Одним из полезных приложений eval()
является оценка выражений python из строки. Например, загрузка из файлового строкового представления словаря:
running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()
Прочитайте его как переменную и отредактируйте ее:
fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction
Выход:
{'Greeting': 'Hello world'}
eval()
интерпретирует строку как код. Причина, по которой так много людей предупреждала вас об использовании этого, заключается в том, что пользователь может использовать это как вариант для запуска кода на компьютере. Если вы импортировали eval(input())
и os
, человек может ввести в input()
os.system('rm -R *')
, который удалит все ваши файлы в вашем домашнем каталоге. (Предположим, что у вас есть система unix). Использование eval()
- это дыра в безопасности. Если вам нужно преобразовать строки в другие форматы, попробуйте использовать те вещи, которые делают это, например int()
.
Возможно, вводящий в заблуждение пример чтения строки и интерпретации.
Попробуйте eval(input())
и введите "1+1"
- это должно печатать 2
. Eval оценивает выражения.
Лот хороших ответов здесь, но никто не описывает использование eval
в контексте его globals=
и locals=
kwargs. Они могут использоваться для ограничения методов, доступных с помощью метода eval
. Например, если вы загрузите новый интерпретатор python, locals()
и globals()
будут такими же и выглядят примерно так:
>>> globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
'__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
'__package__': None, '__name__': '__main__'}
В модуле builtins
есть определенные методы, которые могут наносят значительный ущерб системе. Но можно блокировать все и все, что мы не хотим. Давайте возьмем пример. Предположим, мы хотим построить список для представления домена доступных ядер в системе. Для меня у меня 8 ядер, поэтому мне нужен список [1, 8]
.
>>>from os import cpu_count()
>>>eval('[1, cpu_count()'])
[1, 8]
Также доступно все __builtins__
.
>>>eval('abs(-1)')
1
Хорошо. Таким образом, мы видим один метод, который мы хотим разоблачить, и пример одного (из многих, который может быть гораздо более коварным), который мы не хотим показывать. Итак, блокируем все.
>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable
Мы эффективно заблокировали все методы __builtins__
и, таким образом, обеспечили уровень защиты в нашей системе. На этом этапе мы можем начать добавлять обратно методы, которые мы хотим обнародовать.
>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable
Теперь у нас есть доступный метод cpu_count, все еще блокируя все, что мы не хотим. На мой взгляд, это супермощно и ясно из сферы других ответов, не являющихся общей реализацией. Существует множество применений для чего-то подобного и до тех пор, пока они обрабатываются правильно, я лично чувствую, что eval
можно безопасно использовать для большой ценности.
N.B.
Что-то еще, что круто об этом kwargs
, заключается в том, что вы можете начать использовать сокращенную версию вашего кода. Предположим, вы используете eval как часть конвейера для выполнения импортированного текста. Текст не обязательно должен содержать точный код, он может следовать за некоторым форматом файла шаблонов и все равно выполнять все, что угодно. Например:
>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
В Python 2.x input(...)
эквивалентно eval(raw_input(...))
, в Python 3.x raw_input
было переименовано input
, что, как я подозреваю, привело к вашей путанице (вы, вероятно, смотрели документацию для input
в Python 2.x). Кроме того, eval(input(...))
будет работать отлично в Python 3.x, но поднимет TypeError
в Python 2.
В этом случае eval
используется для принудительного перевода строки, возвращенной с input
, в выражения и интерпретации. Обычно это считается плохой практикой.
Я опаздываю, чтобы ответить на этот вопрос, но никто, кажется, не дает ясного ответа на вопрос.
Если пользователь вводит числовое значение, input()
вернет строку.
>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'
Итак, eval()
будет оценивать возвращаемое значение (или выражение), которое является строкой, и возвращает целое число / float.
>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>>
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14
Конечно, это плохая практика. int()
или float()
следует использовать вместо eval()
в этом случае.
>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14