Превращение строки в переменную
Изучал способы форматирования и наткнулся на такую штуку :
test = 'Name'
exec('{0} = {1}'.format(test, 10))
a = Name # Python жалуется на Unresolved reference 'Name' При этом код воспроизводится без ошибок.
print(a) # Вывод: 10 Где в данный момент хранится переменная Name?
print(Name-5) # Вывод: 5
print(test) # Вывод: 'Name'
Первый вопрос, что это такое и почему это вообще работает? Вот аналогичная запись с помощью %-форматирования :
exec('%s = %d' % (test, 10)) # Работает так же как и метод .format() - без проблем.
А вот аналогичная запись с помощью f-форматирования почему-то уже не работает :
exec(f'{(test := 10)}') # Эквивалентная запись с помощью f-форматирования выдаёт NameError: name 'Name' is not defined. Did you mean: 'name'? То есть как и должно работать.
Собственно второй вопрос, чем f-строки отличаются от других видов форматирования при воспроизведении вышеописанного кода? Почему только здесь не работает?
Ответы (1 шт):
А давайте попробуем не делать exec
, а напечатаем ваши строки. И в конце ещё напечатаем значение переменной test
:
test = 'Name'
print('{0} = {1}'.format(test, 10))
print('%s = %d' % (test, 10))
print(f'{(test := 10)}')
print(test)
Вывод:
Name = 10
Name = 10
10
10
Ой как интересно. Первые два exec
выполняют действие Name = 10
. А последний ваш exec
выполняет то, что возвращает действие test := 10
после того, как его результат преобразован в строку. Если бы вы написали test = 10
, то сразу бы поняли, в чём ошибка. И я подозреваю, что вы так и сделали, и только после этого поменяли =
на :=
, потому что так было написано в подсказке в ошибке:
SyntaxError: f-string: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
То есть тут сначала делается действие test := 10
, а потом уже то, что получается при этом присваивании через "моржовый оператор", пытается выполниться через exec
.
Кстати, отдельно непонятно, как вы умудрились в этой строке получить ошибку с "Name". Извольте предоставить полный трейс ошибки, меня терзают смутные сомнения, что код был какой-то другой у вас при этой ошибке. Текущее содержимое переменной test
в этом действии совсем никак не участвует, поэтому "Name" там не откуда взяться.
Резюмирую. Не важно, как вы сгенерировали строку, с помощью какого стиля форматирования, exec
всегда работает одинаково, если строка одинаковая. Чудес не бывает. А вот операторы x = y
и x := y
работают немного по-разному. И обычное присваивание вы не сможете написать в f-строке при выводе переменной. Но если сделаете такую же строку, как и предыдущие, то всё будет как раньше, см. комментарий strawdog.