Python 3のf-String:改善された文字列フォーマット構文(ガイド)

Python 3のf-Strings:改善された文字列フォーマット構文(ガイド)

Python 3.6の時点では、f-stringは文字列をフォーマットするための素晴らしい新しい方法です。 他のフォーマット方法よりも読みやすく、簡潔で、エラーが少ないだけでなく、高速です!

この記事の終わりまでに、今日からF文字列の使用を開始する方法と理由を学習します。

しかし、最初に、雪の中で両方の道を登って学校に行かなければならなかったとき、f-stringsの前の生活はどのようなものでしたか。

無料のPDFダウンロード: Python3チートシート

Pythonでの「昔ながらの」文字列フォーマット

Python 3.6より前は、フォーマット用の文字列リテラル内にPython式を埋め込む主な方法が2つありました。%-フォーマットとstr.format()です。 それらの使用方法とその制限を確認しようとしています。

オプション#1:%-formatting

これはPythonフォーマットのOGであり、最初から言語で使用されてきました。 詳細については、Python docsを参照してください。 次の注意事項が含まれているドキュメントでは、%書式設定は推奨されないことに注意してください。

「ここで説明する書式設定操作には、多くの一般的なエラー(タプルや辞書を正しく表示できないなど)につながるさまざまな癖があります。

新しい形式の文字列リテラルまたはstr.format()インターフェイスを使用すると、これらのエラーを回避できます。 これらの代替手段は、テキストをフォーマットするためのより強力で柔軟かつ拡張可能なアプローチも提供します。」 (Source

%フォーマットの使用方法

文字列オブジェクトには、%演算子を使用した組み込み操作があり、これを使用して文字列をフォーマットできます。 実際には次のようになります。

>>>

>>> name = "Eric"
>>> "Hello, %s." % name
'Hello, Eric.'

複数の変数を挿入するには、それらの変数のタプルを使用する必要があります。 その方法は次のとおりです。

>>>

>>> name = "Eric"
>>> age = 74
>>> "Hello, %s. You are %s." % (name, age)
'Hello Eric. You are 74.'
%-formattingが優れていない理由

上で見たコード例は十分に読みやすいです。 ただし、いくつかのパラメーターと長い文字列の使用を開始すると、コードはすぐに読みにくくなります。 物事はすでに少し厄介に見え始めています:

>>>

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> "Hello, %s %s. You are %s. You are a %s. You were a member of %s." % (first_name, last_name, age, profession, affiliation)
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'

残念ながら、この種の書式設定は冗長であり、タプルや辞書を正しく表示しないなどのエラーにつながるため、あまり適していません。 幸いなことに、明るい日があります。

オプション#2:str.format()

この新しい仕事の方法はPython 2.6で導入されました。 詳細については、Python docsを確認してください。

str.format()の使用方法

str.format()は%フォーマットの改善です。 これは通常の関数呼び出し構文を使用し、文字列に変換されるオブジェクトのextensible through the __format__() methodです。

str.format()を使用すると、置換フィールドは中括弧でマークされます。

>>>

>>> "Hello, {}. You are {}.".format(name, age)
'Hello, Eric. You are 74.'

インデックスを参照することで、変数を任意の順序で参照できます。

>>>

>>> "Hello, {1}. You are {0}.".format(age, name)
'Hello, Eric. You are 74.'

しかし、変数名を挿入すると、オブジェクトを渡すことができ、その後に括弧と括弧で囲まれたパラメーターとメソッドを参照できるという追加の特典が得られます。

>>>

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(name=person['name'], age=person['age'])
'Hello, Eric. You are 74.'

**を使用して、辞書でこの巧妙なトリックを実行することもできます。

>>>

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(**person)
'Hello, Eric. You are 74.'

str.format()は、%-formattingと比較すると間違いなくアップグレードですが、すべてがバラと太陽の光ではありません。

str.format()が優れていない理由

str.format()を使用するコードは、%-formattingを使用するコードよりもはるかに読みやすくなりますが、複数のパラメーターや長い文字列を処理する場合は、str.format()が非常に冗長になる可能性があります。 これをみて:

>>>

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> print(("Hello, {first_name} {last_name}. You are {age}. " +
>>>        "You are a {profession}. You were a member of {affiliation}.") \
>>>        .format(first_name=first_name, last_name=last_name, age=age, \
>>>                profession=profession, affiliation=affiliation))
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'

辞書に.format()に渡したい変数がある場合は、.format(**some_dict)で解凍し、文字列のキーで値を参照できますが、もっと良い方法が必要です。これをする。

f-Strings:Pythonで文字列をフォーマットする新しい改善された方法

良いニュースは、f文字列が1日を節約するためにここにあるということです。 彼らはスライス! 彼らはサイコロ! 彼らは千切りフライを作ります! わかりました、それらはそれらのどれもしませんが、フォーマットをより簡単にします。 彼らはPython 3.6でパーティーに参加しました。 それについては、Eric Vによって書かれたPEP 498ですべて読むことができます。 2015年8月のスミス。

「フォーマットされた文字列リテラル」とも呼ばれるf文字列は、先頭にfがあり、値に置き換えられる式を含む中括弧が付いた文字列リテラルです。 式は実行時に評価され、__format__プロトコルを使用してフォーマットされます。 いつものように、あなたがもっと学びたいとき、Python docsはあなたの友達です。

以下は、f-stringsがあなたの人生を楽にする方法のいくつかです。

簡単な構文

構文はstr.format()で使用したものと似ていますが、冗長性は低くなります。 これがどれほど簡単に読めるかを見てください。

>>>

>>> name = "Eric"
>>> age = 74
>>> f"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.'

大文字のFを使用することも有効です。

>>>

>>> F"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.'

あなたはまだf弦が好きですか? この記事の終わりまでに、>>> F"Yes!"と答えていただければ幸いです。

任意の表現

f文字列は実行時に評価されるため、有効なPython式をすべて含めることができます。 これにより、気の利いたことができます。

次のように、非常に簡単なことができます。

>>>

>>> f"{2 * 37}"
'74'

ただし、関数を呼び出すこともできます。 例を示しましょう。

>>>

>>> def to_lowercase(input):
...     return input.lower()

>>> name = "Eric Idle"
>>> f"{to_lowercase(name)} is funny."
'eric idle is funny.'

メソッドを直接呼び出すオプションもあります。

>>>

>>> f"{name.lower()} is funny."
'eric idle is funny.'

F文字列を持つクラスから作成されたオブジェクトを使用することもできます。 次のクラスがあると想像してください。

class Comedian:
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def __str__(self):
        return f"{self.first_name} {self.last_name} is {self.age}."

    def __repr__(self):
        return f"{self.first_name} {self.last_name} is {self.age}. Surprise!"

あなたはこれを行うことができるでしょう:

>>>

>>> new_comedian = Comedian("Eric", "Idle", "74")
>>> f"{new_comedian}"
'Eric Idle is 74.'

The __str__() and __repr__() methodsは、オブジェクトが文字列として表示される方法を処理するため、クラス定義にこれらのメソッドの少なくとも1つを含める必要があります。 いずれかを選択する必要がある場合は、__str__()の代わりに使用できるため、__repr__()を使用してください。

__str__()によって返される文字列は、オブジェクトの非公式な文字列表現であり、読み取り可能である必要があります。 __repr__()によって返される文字列は公式の表現であり、明確である必要があります。 __str__()__repr__()を直接使用するよりも、str()repr()を呼び出す方が望ましいです。

デフォルトでは、f文字列は__str__()を使用しますが、変換フラグ!rを含めると、確実に__repr__()を使用できます。

>>>

>>> f"{new_comedian}"
'Eric Idle is 74.'
>>> f"{new_comedian!r}"
'Eric Idle is 74. Surprise!'

完全なPython式をサポートするf文字列をもたらした会話の一部を読みたい場合は、hereを読むことができます。

複数行のf文字列

複数行の文字列を使用できます。

>>>

>>> name = "Eric"
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> message = (
...     f"Hi {name}. "
...     f"You are a {profession}. "
...     f"You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.'

ただし、複数行の文字列の各行の前にfを配置する必要があることに注意してください。 次のコードは機能しません。

>>>

>>> message = (
...     f"Hi {name}. "
...     "You are a {profession}. "
...     "You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a {profession}. You were in {affiliation}.'

個々の行の前にfを付けない場合は、通常の古いガーデンバラエティの弦だけが使用され、光沢のある新しい派手なf弦は使用できません。

文字列を複数行に分散させたい場合は、\を使用してリターンをエスケープするオプションもあります。

>>>

>>> message = f"Hi {name}. " \
...           f"You are a {profession}. " \
...           f"You were in {affiliation}."
...
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.'

しかし、これは、"""を使用した場合に発生することです。

>>>

>>> message = f"""
...     Hi {name}.
...     You are a {profession}.
...     You were in {affiliation}.
... """
...
>>> message
'\n    Hi Eric.\n    You are a comedian.\n    You were in Monty Python.\n'

PEP 8のインデントガイドラインを読んでください。

速度

f文字列のfは、「高速」を表す場合もあります。

f-stringは、%-formattingと%(t​​0)sの両方よりも高速です。 既に見たように、f-stringは定数値ではなく、実行時に評価される式です。 ドキュメントからの抜粋は次のとおりです。

「F文字列は、最小限の構文を使用して、文字列リテラル内に式を埋め込む方法を提供します。 f文字列は実際には実行時に評価される式であり、定数値ではないことに注意してください。 Pythonソースコードでは、f文字列はリテラル文字列であり、接頭辞fが付いており、中括弧内に式が含まれています。 式はそれらの値に置き換えられます。」 (Source

実行時に、中括弧内の式は独自のスコープで評価され、f-stringの文字列リテラル部分と一緒になります。 結果の文字列が返されます。 それだけです。

速度の比較は次のとおりです。

>>>

>>> import timeit
>>> timeit.timeit("""name = "Eric"
... age = 74
... '%s is %s.' % (name, age)""", number = 10000)
0.003324444866599663

>>>

>>> timeit.timeit("""name = "Eric"
... age = 74
... '{} is {}.'.format(name, age)""", number = 10000)
0.004242089427570761

>>>

>>> timeit.timeit("""name = "Eric"
... age = 74
... f'{name} is {age}.'""", number = 10000)
0.0024820892040722242

ご覧のとおり、fストリングが上に出ています。

ただし、常にそうとは限りませんでした。 それらが最初に実装されたとき、それらにはいくつかのspeed issuesがあり、str.format()よりも高速にする必要がありました。 特別なBUILD_STRING opcodeが導入されました。

Python f-ストリング:厄介な詳細

f-stringsが優れている理由をすべて理解できたので、f-stringsを使用して使い始めたいと思います。 この勇敢な新しい世界に挑戦する際に留意すべきいくつかの詳細を以下に示します。

引用符

式内でさまざまなタイプの引用符を使用できます。 式で使用しているのと同じタイプの引用符をf-stringの外側で使用していないことを確認してください。

このコードは動作します。

>>>

>>> f"{'Eric Idle'}"
'Eric Idle'

このコードも動作します:

>>>

>>> f'{"Eric Idle"}'
'Eric Idle'

三重引用符も使用できます。

>>>

>>> f"""Eric Idle"""
'Eric Idle'

>>>

>>> f'''Eric Idle'''
'Eric Idle'

文字列の内側と外側の両方で同じタイプの引用符を使用する必要がある場合は、\でエスケープできます。

>>>

>>> f"The \"comedian\" is {name}, aged {age}."
'The "comedian" is Eric Idle, aged 74.'

辞書

引用符といえば、辞書で作業しているときは注意してください。 辞書のキーに一重引用符を使用する場合は、キーを含むf文字列に二重引用符を使用していることを忘れないでください。

これは動作します:

>>>

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f"The comedian is {comedian['name']}, aged {comedian['age']}."
The comedian is Eric Idle, aged 74.

しかし、これは構文エラーを伴う大混乱になります。

>>>

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f'The comedian is {comedian['name']}, aged {comedian['age']}.'
  File "", line 1
    f'The comedian is {comedian['name']}, aged {comedian['age']}.'
                                    ^
SyntaxError: invalid syntax

f-stringの外側で使用するのと同じタイプのクォーテーションマークをディクショナリキーの周りで使用する場合、最初のディクショナリキーの先頭のクォーテーションマークは文字列の終わりとして解釈されます。

中括弧

文字列に中括弧を表示するには、二重中括弧を使用する必要があります。

>>>

>>> f"{{74}}"
'{74}'

トリプルブレースを使用すると、ストリング内にシングルブレースのみが存在することに注意してください。

>>>

>>> f"{{{74}}}"
'{74}'

ただし、3つ以上のブレースを使用する場合は、表示するブレースを増やすことができます。

>>>

>>> f"{{{{74}}}}"
'{{74}}'

バックスラッシュ

前に見たように、f文字列の文字列部分でバックスラッシュエスケープを使用することができます。 ただし、バックスラッシュを使用してf文字列の式部分でエスケープすることはできません。

>>>

>>> f"{\"Eric Idle\"}"
  File "", line 1
    f"{\"Eric Idle\"}"
                      ^
SyntaxError: f-string expression part cannot include a backslash

事前に式を評価し、結果をf文字列で使用することで、この問題を回避できます。

>>>

>>> name = "Eric Idle"
>>> f"{name}"
'Eric Idle'

式には、#記号を使用したコメントを含めないでください。 構文エラーが表示されます:

>>>

>>> f"Eric is {2 * 37 #Oh my!}."
  File "", line 1
    f"Eric is {2 * 37 #Oh my!}."
                                ^
SyntaxError: f-string expression part cannot include '#'

フォースアンドフォーマット!

文字列をフォーマットする古い方法を引き続き使用できますが、f文字列を使用すると、より簡潔で読みやすく、便利で、より高速でエラーが発生しにくい方法を使用できます。 f-stringsを使用して生活を簡素化することは、まだ切り替えを行っていない場合にPython 3.6を使い始める大きな理由です。 (Python 2をまだ使用している場合は、2020がまもなく登場することを忘れないでください!)

Zen of Pythonによると、何かを行う方法を決定する必要がある場合は、「[t]ここに1つ、できれば1つだけの明白な方法が必要です」。文字列をフォーマットする方法はf文字列だけではありませんが、仕事を遂行するための1つの明白な方法になるのに最適な位置にあります。

参考文献

文字列補間に関する詳細な説明を読みたい場合は、PEP 502をご覧ください。 また、PEP 536 draftには、f文字列の将来についてもう少し考えがあります。

無料のPDFダウンロード: Python3チートシート

文字列をさらに楽しむには、次の記事をご覧ください。

ハッピーパイソン!