web-dev-qa-db-ja.com

文字列をf文字列に変換するにはどうすればよいですか?

私はこれを読んでいた blog pythonの新しいf-stringsで、本当にすてきだと思われる。ただし、文字列またはファイルから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'
20
piRSquared

f文字列はコードです。安全な「もちろん文字列リテラルはコード」の方法だけでなく、危険な、任意のコードの実行方法でもあります。これは有効なf文字列です。

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

そして、評価時に任意のシェルコマンドを実行します。

テキストファイルからロードされた文字列を取得してコードとして評価する方法を尋ねているのですが、答えはevalに要約されます。これは、もちろんセキュリティリスクおよびおそらく悪いアイデアなので、ファイルからf-stringをロードしないことをお勧めします。

ファイルから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-stringsをロードするソースに非常に注意してください。

15
user2357112

しかし、文字列sがあった場合はどうなりますか?次のようなsを有効化できるようにしたい:

name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)

AFAIU、 PEP 498-Literal String Interpolation によると、これは不可能です1。プログラムでf文字列を作成する方法はありません。

Pythonソースコード、f-stringは、中括弧内に式を含む、 'f'が先頭に付くリテラル文字列です。


1もちろん、@ coldspeedで述べたようにexecのようなものを使用しても構わないでしょう。しかし、その時点で、短所はおそらく長所を上回っています。

5
Christian Dean

簡単な解決策は、f-stringsと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-stringで参照されている変数をその呼び出しの周りのスコープからプルしようとします。指摘したように、evalを使用することは潜在的に危険ですが、ソースを知っていれば、他のコードを実行するよりも危険ではないと思います。

5
Jarno