新しいPython 3.6 f-stringsは、文字列の使いやすさの大きな飛躍のように思えます。古いインタープリターで実行されている可能性のある新しいプロジェクトに心から飛び入り採用したいと思います。 2.7、3.3-3.5のサポートは素晴らしいと思いますが、少なくともこれらをPython 3.5コードベースで使用したいと思います。古いインタープリターで使用するために3.6のフォーマットされた文字列リテラルをインポートするには? ?
f"Foo is {age} {units} old"
のようなフォーマットされた文字列リテラルは変更を壊さないため、from __future__ import ...
呼び出しには含まれないことを理解しています。しかし、変更はバックポートされていません(私の知る限り)f-stringsで記述する新しいコードは、Python 3.6+多くのプロジェクト。
残念ながら、それを使用したい場合は、行列乗算演算子Python 3.6+
および@
またはPython 3.5+
(yield from
と同じ)と同じPython 3.4+
が必要です。
これらは、コードの解釈方法に変更を加えたため、古いバージョンでインポートされたときにSyntaxErrorsをスローします。つまり、古いPythonにインポートされていない場所、またはeval
またはexec
で保護されていない場所にそれらを配置する必要があります(後者2つはお勧めしません!)。
複数のpythonバージョンをサポートしたい場合、それらを簡単に使用することはできません。
future-fstrings はf-stringsをPython 2.7スクリプトにもたらします。(ドキュメントに基づいて3.3-3.5を想定しています。)
pip install future-fstrings
経由でpipインストールしたら、コードの先頭に特別な行を配置する必要があります。その行は次のとおりです。
# -*- coding: future_fstrings -*-
次に、コード内でフォーマットされた文字列リテラル(f-strings)を使用できます。
# -*- coding: future_fstrings -*-
var = 'f-string'
print(f'hello world, this is an {var}')
ここに私が使用するものがあります:
text = "Foo is {age} {units} old".format(**locals())
locals()
によって返された辞書をアンパック(**
)します。これは、すべてのローカル変数を辞書として{variable_name: value}
注これは、nonlocal
(Python 3.0+)を使用してローカルスコープにインポートしない限り、外部スコープで宣言された変数では機能しません。
あなたも使用できます
text.format(**locals(),**globals())
文字列にグローバル変数を含めるため。
Fストリングは、f
プレフィックスのトークン化時にインタープリターによって作成されます。その機能だけで互換性の可能性がすべて失われます。
最も近いショットは、次のようなキーワードのフォーマットを使用することです
'Foo is {age} {units} old'.format(age=age, units=units)
互換性の要件が終了すると、より簡単にリファクタリングできます。
f-stringの _f2format
_ と呼ばれるバックポートコンパイラを作成しました。あなたが要求したように、f-stringリテラルをPython 3.6風味で書き、コンパイルしてJavaScriptの Babel
と同様に、エンドユーザーが実行できる互換バージョン。
_f2format
_は、バックポートコンパイラーのインテリジェントでありながら不完全なソリューションを提供します。ソースコードの元のレイアウトを維持しながら、f-stringリテラルを_str.format
_メソッドに置き換えます。単純に使用できます
_f2format /path/to/the/file_or_directory
_
すべてのPythonファイルを所定の場所に書き換えます。たとえば、
var = f'foo{(1+2)*3:>5}bar{"a", "b"!r}boo'
に変換されます
var = ('foo{:>5}bar{!r}boo').format(((1+2)*3), ("a", "b"))
文字列の連結、変換、形式の指定、複数行およびユニコードはすべて適切に扱われます。また、_f2format
_は、構文違反があった場合に元のファイルをアーカイブします。
simpleeval
を使用したダーティソリューション
import re
import simpleeval
test='_someString'
lst = ['_456']
s = '123123{lst[0]}{test}'
def template__format(template, context=None):
if context is None:
frame = inspect.currentframe()
context = frame.f_back.f_locals
del frame
ptn = '([^{]?){([^}]+)}'
class counter():
i = -1
def count(m):
counter.i += 1
return m.expand('\\1{%d}'%counter.i)
template = re.sub(ptn,string=s, repl= count)
exprs = [x[1] for x in re.findall(ptn,s)]
vals = map(simpleeval.SimpleEval(names=context).eval,exprs)
res = template.format(*vals)
return res
print (template__format(s))