Как мне преобразовать строку в f-строку?
Я читал этот блог на Python о новых f-строках, и они кажутся действительно аккуратными. Однако я хочу иметь возможность загружать f-строку из строки или файла.
Я не могу найти какой-либо строковый метод или другую функцию, которая делает это.
Из примера в моей ссылке выше:
name = 'Fred'
age = 42
f"My name is {name} and I am {age} years old"
'My name is Fred and I am 42 years old'
Но что, если бы у меня была строка s
? Я хочу быть в состоянии эффективно s
, что-то вроде этого:
name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
Оказывается, я уже могу выполнить что-то похожее на str.format
и получить повышение производительности. А именно:
format = lambda name, age: f"My name is {name} and I am {age} years old"
format('Ted', 12)
'My name is Ted and I am 12 years old'
Ответы
Ответ 1
f-строки - это код. Не только в сейфе, "конечно, строковый литерал является кодом", но и опасным, произвольным способом исполнения кода. Это допустимая строка f:
f"{__import__('os').system('install ransomware or something')}"
и он будет выполнять произвольные команды оболочки при оценке.
Вы спрашиваете, как взять строку, загруженную из текстового файла, и оценить ее как код, а ответ сводится к eval
. Это, конечно, риск безопасности и , вероятно, плохая идея, поэтому я рекомендую не пытаться загрузить f-строки из файлов.
Если вы хотите загрузить f-string f"My name is {name} and I am {age} years old"
из файла, тогда на самом деле поставьте
f"My name is {name} and I am {age} years old"
в файле, f
и кавычки и все.
Прочитайте его из файла, скомпилируйте его и сохраните (так что eval
не нужно перекомпилировать его каждый раз):
compiled_fstring = compile(fstring_from_file, '<fstring_from_file>', 'eval')
и оцените его с помощью eval
:
formatted_output = eval(compiled_fstring)
Если вы это сделаете, будьте очень осторожны с источниками, из которых вы загрузите свои f-строки.
Ответ 2
Но что если бы у меня была строка s? Я хочу быть в состоянии, что-то вроде этого:
name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
AFAIU, Согласно PEP 498 - Интерполяция буквенных строк, это невозможно 1. Нет способа программно создать f-строку:
В исходном коде Python f-строка является литеральной строкой с префиксом 'f', которая содержит выражения внутри фигурных скобок.
1Если, конечно, вы захотите использовать что-то вроде exec
, как упоминалось в @coldspeed. Но на этом этапе минусы, вероятно, перевешивают плюсы.
Ответ 3
Простым решением было бы использовать f-строки и eval.
def effify(non_f_str: str):
return eval(f'f"""{non_f_str}"""')
name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
'My name is Fred and I am 42 years old'
Это в основном добавляет "f" к строке и затем оценивается как код. Тройные кавычки также помогают разместить многострочные строки. Функция будет пытаться вытащить переменные, на которые есть ссылка в f-строке, из области вокруг своего вызова. Как уже указывалось, использование eval
может быть опасным, но если вы знаете свой источник, то я думаю, что это не более опасно, чем выполнение любого другого кода.