1. ホーム
  2. python

[解決済み] f-stringの評価を遅らせるには?

2022-05-24 05:33:27

質問

私はいくつかのファイルを生成するためにテンプレート文字列を使用しており、私はこの目的のために新しいf-stringの簡潔さを愛し、私の以前のテンプレートコードをこのようなものから減らすために。

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a.format(**locals()))

これで、直接変数を置き換えて、できるようになりました。

names = ["foo", "bar"]
for name in names:
    print (f"The current name is {name}")

しかし、時には、テンプレートを他の場所、つまりコードの上位に定義したり、ファイルか何かからインポートしたりすることが理にかなっていることがあります。これは、テンプレートが静的な文字列で、その中に書式設定タグがあることを意味します。文字列を新しい f-文字列として解釈するようにインタープリタに指示するために、文字列に何かが起こる必要がありますが、そのようなものがあるかどうかはわかりません。

文字列を持ち込んで、それが f-文字列として解釈されるようにする方法はありますか。 .format(**locals()) の呼び出しを避けることができますか?

理想的には、このようなコードを書けるようにしたいのですが...(ここで magic_fstring_function は私が理解していない部分です)。

template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
    print (template_a)

...このような出力が期待できます(ファイルを2回読まなくても)。

The current name is foo
The current name is bar

...ですが、実際に得られる出力は

The current name is {name}
The current name is {name}

どのように解決するのですか?

理想2」の完成形です。

これはf-stringではありません-f-stringを使うことさえしません-しかし、要求されたとおりに実行します。指定されたとおりの構文です。を使用していないので、セキュリティ上の問題はありません。 eval() .

これは小さなクラスを使用し、実装は __str__ を実装しており、print からは自動的に呼び出されます。クラスの限られた範囲から逃れるために、私たちは inspect モジュールを使って1つ上のフレームにホップし、呼び出し元がアクセスする変数を見ることができます。

import inspect

class magic_fstring_function:
    def __init__(self, payload):
        self.payload = payload
    def __str__(self):
        vars = inspect.currentframe().f_back.f_globals.copy()
        vars.update(inspect.currentframe().f_back.f_locals)
        return self.payload.format(**vars)

template = "The current name is {name}"

template_a = magic_fstring_function(template)

# use it inside a function to demonstrate it gets the scoping right
def new_scope():
    names = ["foo", "bar"]
    for name in names:
        print(template_a)

new_scope()
# The current name is foo
# The current name is bar