Где определены переменные метода exec ()?

1

Я пытался запустить небольшой код, который преобразует строку в список, когда я почувствовал эту проблему. Прежде всего здесь приведен пример кода:

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 из-за пределов функции, и тот факт, что я могу запустить этот код один, я не могу понять, где проблема.

Я пробую некоторые поиски в Интернете, но из-за недостатка знаний в низкоуровневом исполнении я не могу найти ключевые слова, которые определяют мою конкретную проблему. Спасибо за вашу помощь.

  • 0
    Как вы думаете, зачем вам нужно exec для этой задачи? FWIW, ваш второй кодовый блок устанавливает res в строку '[0. 1. 0. 0. 0. 2. 5.]' ; это не создает список.
  • 0
    @ PM2Ring Это просто для примера, я упростил код, чтобы быть уверенным, что ошибка не вызвана чем-то другим.
Теги:
variables
exec

2 ответа

1
Лучший ответ

Как объясняется в документах 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'>
1

В CPython локальные переменные в функции (обычно?) Хранятся в массиве фиксированного размера в оптимизации, известной как "быстрые локальные". В результате локальные переменные не могут динамически добавляться к функции.

Функция exec попытается добавить новую локальную переменную в функцию, но она не будет считана оператором return, потому что этот массив фиксированного размера не изменился.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню