Я пытался запустить небольшой код, который преобразует строку в список, когда я почувствовал эту проблему. Прежде всего здесь приведен пример кода:
def str_to_list(s):
s = s.replace('\n', '')
exec('res="{}"'.format(str(s)))
print(res)
s = '[0. 1. 0. 0.\n 0. 2. 5.]'
l = str_to_list(s)
Когда я запускаю это, я получаю NameError о res
, сначала я думал, что это может быть своего рода локальные переменные в методе exec(), но затем я понял, что могу запустить этот код:
s = '[0. 1. 0. 0.\n 0. 2. 5.]'
s = s.replace('\n', '')
exec('res="{}"'.format(str(s)))
print(res)
Поскольку тот факт, что я не пытаюсь вызвать res
из-за пределов функции, и тот факт, что я могу запустить этот код один, я не могу понять, где проблема.
Я пробую некоторые поиски в Интернете, но из-за недостатка знаний в низкоуровневом исполнении я не могу найти ключевые слова, которые определяют мою конкретную проблему. Спасибо за вашу помощь.
Как объясняется в документах exec
вам нужно предоставить exec
соответствующий словарь locals
. Например,
def str_to_list(s):
s = s.replace('\n', '')
d = {}
exec('res="{}"'.format(s), None, d)
return d['res']
s = '[0. 1. 0. 0.\n 0. 2. 5.]'
print(str_to_list(s))
выход
[0. 1. 0. 0. 0. 2. 5.]
Однако обычно рекомендуется избегать использования exec
, если только вам это не нужно. Для получения дополнительной информации см. Ned Batchelder Eval действительно опасно. Информация там также применима к exec
.
Если вы просто хотите создать список из строки, вы, вероятно, можете использовать ast.literal_eval
. Например,
from ast import literal_eval
s = '[0, 1, 0, 0, 0, 2, 5]'
seq = literal_eval(s)
print(seq, type(seq))
выход
[0, 1, 0, 0, 0, 2, 5] <class 'list'>
В CPython локальные переменные в функции (обычно?) Хранятся в массиве фиксированного размера в оптимизации, известной как "быстрые локальные". В результате локальные переменные не могут динамически добавляться к функции.
Функция exec попытается добавить новую локальную переменную в функцию, но она не будет считана оператором return, потому что этот массив фиксированного размера не изменился.
exec
для этой задачи? FWIW, ваш второй кодовый блок устанавливаетres
в строку'[0. 1. 0. 0. 0. 2. 5.]'
; это не создает список.