7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Python][小ネタ] f文字列中で利用されるconversion flag,あるいは変換フラグ(!s, !r, !a)について

Last updated at Posted at 2021-03-28

概要

Effective Pythonを読んでいると以下のようなコードが。

class Tool:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def __repr__(self):
        return f'Tool({self.name!r}, {self.weight})'

f文字列自体は日頃から利用していますし、reprメソッドについては「strメソッドよりオフィシャルな返り値で、strメソッドがなかったら代わりに呼び出されたりする」程度の認識はあります。(参考サイト: Python-特殊メソッド: __repr__と__str__)

ですが、そのf文字列中で利用されている!rについては全くの初見でした。エクスクラメーションマークは特殊文字扱いなのかGoogleで検索しても上手くヒットしませんし、正式な名称も知らないので無駄に手こずる有様。

ここでは同じような疑問にぶち当たった方のために、メモがてら記事を残しておきます。

結論

ざっくり言ってしまうと、f文字列中の!は、文字列内の{}のところを評価するために呼び出すメソッドを決定するためのものです。公式サイトには以下のように表記があります。

If a conversion is specified, the result of evaluating the expression is converted before formatting. Conversion '!s' calls str() on the result, '!r' calls repr(), and '!a' calls ascii().

和訳するとこんな感じでしょうか。

変換が指定されると、表現を評価した結果がフォーマッティングの前に変換されます。!sではstrメソッドが、!rではreprメソッドが、!aではasciiメソッドが呼ばれます。

簡単なサンプルを作るとこんな感じ?

class Sample:
    def __init__(self):
        pass
    
    def __repr__(self):
        return "__repr__ method is called."
    
    def __str__(self):
        return "__str__ method is called."
    
    def __ascii__(self):
        return "__ascii__ method is called."


sample = Sample()
print(f"{sample!r}")
print(f"{sample!s}")
print(f"{sample!a}")
出力結果
__repr__ method is called.
__str__ method is called.
__repr__ method is called.

ちなみに、何も指定していないとstrメソッドが呼ばれるようになっています。

print(f"{sample}")
出力結果
__str__ method is called.

まとめ

ということで、変換フラグについての理解はある程度深まりました。冒頭のコードで用いられている!rは、strクラスに実装されている__repr__メソッドを呼び出すための変換フラグということになります。

上と同じ様に3種の変換フラグを使ってf文字列をprintすると、以下のようになります。

sample_text = "sample"

print(f"{sample_text!r}")
print(f"{sample_text!s}")
print(f"{sample_text!a}")
print(f"{sample_text}")
出力結果
'sample'
sample
'sample'
sample

……正直、'がついているかいないかくらいの違いで大した差はないんじゃない?と思ってしまいます。が、よくよく考えると、文字列であることをきちんと明示させるためには、__repr__メソッドを使うのが賢い気もします。

ここまで読んでくださってありがとうございます。誤りに気づかれたり、あるいは「こんな利点、利用方法があるよ」という知見をお持ちの方は、ぜひコメントにて情報提供していただけると幸いです。

集合知に感謝。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?