Как работает следующий фрагмент кода?

Я новичок в python и просматриваю проект с открытым исходным кодом под названием pyOBD от Donour Sizemore для ELM327 (не совсем уверен, может быть нацелен на большее количество устройств сканирования). Я могу понять, что ниже приведен метод преобразования шестнадцатеричного значения. в int. Но как это работает? Особенно строка с eval в ней.

 def hex_to_int(str):
     i = eval("0x" + str, {}, {})
     return i

person Flame of udun    schedule 23.08.2013    source источник
comment
Это очень, очень плохой код. Не пытайтесь извлечь из этого уроки.   -  person Oleh Prypin    schedule 23.08.2013
comment
возможно, вы можете спросить на codereview.stackexchange.com   -  person    schedule 23.08.2013
comment
Я на самом деле съежился. Я не часто съеживаюсь над кодом.   -  person roippi    schedule 23.08.2013
comment
Это должно было быть int(s, 16) (и параметр должен был называться иначе, чем str).   -  person user2357112 supports Monica    schedule 23.08.2013
comment
@OlehPrypin Не могли бы вы объяснить, что делает этот код таким плохим? Я только новичок, поэтому не могу оценить.   -  person Flame of udun    schedule 23.08.2013
comment
@FoxMaSk Спасибо, буду   -  person Flame of udun    schedule 23.08.2013
comment
Этот код плох по многим причинам: 1) он переопределяет str, встроенный внутри функции. 2) пустые {} абсолютно ничего не делают 3) eval запустит любой код, который вы в него поместите (ОЧЕНЬ опасно) 4) то же самое можно сделать, просто выполнив int(s, 16), где s это строка 5) он взорвется, если вы поместите во что угодно, кроме строки.   -  person    schedule 23.08.2013


Ответы (1)


eval выполняет строку, как если бы это был код Python, а затем выводит результат.

В этом случае он запускает что-то вроде 0xaf, что является способом указания шестнадцатеричного литерала, и выводит результирующее целое число. Попробуйте ввести 0xaf в интерпретатор Python, и в результате вы получите целое число.

eval небезопасно использовать для ненадежного ввода. Например,

eval("0xa and __import__('os').remove('some/file/path')")

может удалить файл в вашей системе.

Лучше использовать ast.literal_eval или int:

>>> import ast
>>> ast.literal_eval("0xaf")
175
>>> int("af", 16)
175

Которые безопасны и дают тот же результат.

person agf    schedule 23.08.2013
comment
О, ладно.. Это действительно отвечает, почему код является нет-нет... но как шестнадцатеричное значение преобразуется в целочисленное значение? - person Flame of udun; 23.08.2013
comment
@JaneLove Потому что Python распознает 0xaf как допустимый код Python и запускает его. Попробуйте ввести это в интерпретатор Python — вы получите целое число в качестве вывода. - person agf; 23.08.2013