Как мне преобразовать строку в f-строку

Я читал этот блог о новых f-строках Python, и они кажутся действительно аккуратными. Тем не менее, я хочу иметь возможность загружать 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'

2 ответа

Решение

F-строки являются кодом. Не только безопасным способом "конечно, строковый литерал - это код", но и опасным способом выполнения произвольного кода. Это допустимая f-строка:

f"{__import__('os').system('install ransomware or something')}"

и он будет выполнять произвольные команды оболочки при оценке.

Вы спрашиваете, как взять строку, загруженную из текстового файла, и оценить ее как код, а ответ сводится к eval, Это, конечно, угроза безопасности и, вероятно, плохая идея, поэтому я не рекомендую загружать f-строки из файлов.

Если вы хотите загрузить F-строку 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-строки.

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

Но что если бы у меня была строка 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. Но на этом этапе минусы, вероятно, перевешивают плюсы.

Другие вопросы по тегам