--- title: String Format in Python description: Introduction to 4 ways of formatting string in Python. tags: python, fstring, percent_string, string_format GA: UA-206161787-1 lang: zh --- ###### tags: `yt` `python` # String Format in Python ## 什麼是String Format? 舉例而言,我們在看YouTube時,在影片的下方都會顯示影片的標題以及影片發布的日期,而這些文字在每部影片中的格式都是一樣的,像是`xx小時前`之類的,有改動的地方只有`xx`,剩下的部分是不變的。這種生成固定格式字串的過程,我們就稱之為String Format。 ## 4種方法 下面我們透過同一個例子來示範這四種常見的的方法。 [完整程式碼](https://colab.research.google.com/drive/1pZNhX48pTOxv1B9_crGjkO6bzhf7ZQJr?usp=sharing) | # | Method | Support | | --- | ------------ | ------------ | | 1 | `+` 串接 | all versions | | 2 | %-string | all versions | | 3 | str.format() | >= python2.6 | | 4 | f-string | >= python3.6 | --- > 我們的目標是要印出標題與發布的日期。 Setup: ```python= from datetime import datetime title = "Python EP 0" timestamp = datetime.now() ``` Output: ``` Title: Python EP 0, Posted on 8/23 ``` ### 1. `+` 串接 第一種方法是透過`+`直接把各個字串組合在一起。 ```python= print("Title: " + title + ", Posted on " + str(timestamp.month) + "/" + str(timestamp.day)) ``` 這種方法很直觀,但要注意,串接在一起的變數都必須是字串,像這邊我們就得把`Timestamp`中的月份與日期透過內建的`str`函式,把他們從`int`轉成`str`,這樣他們才可以正確地被串接在一起。 ### 2. %-string 第二種方法是透過`%-string`,早期的Python就有支援類似C語言的`%-string`語法。使用的方法是,在我們想要替換的位置打上`%s`來標記,隨後透過`%`的Operator傳入一個含有目標字串的`Tuple`,注意,傳入的`Tuple` 必須包含所有要被置換的變數,個數不能多也不能少。像這邊我們有三個`%s`的placeholder,那就得傳入三個變數,分別是`title`和`timestamp`的月份及日期。 ```python= print("Title: %s, Posted on %s/%s" % (title, timestamp.month, timestamp.day)) ``` ### 3. str.format() 第三種方法是呼叫string中foramt的函式,這種方法在Python2.6之後開始支援,使用起來與`%-string`相似,他用大括號(`{}`)來標記要取代的位置,再透過呼叫`format()`的函式,傳入要取代的實際內容。此外,它提供了許多進階的功能,像是能為傳入的變數命名,並且在直接在字串中存取物件的屬性(Attribute)。像這邊,我們就標記並命名了三個要取代的地方,直接在大括號中存取`timestamp`的月份與日期。 ```python= print("Title: {t}, Posted on {ts.month}/{ts.day}".format(t=title, ts=timestamp)) ``` ### 4. f-string 最後一種方法稱為`f-string`,這在Python3.6之後才開始支援。使用的方法是,在定義字串的引號前,加上小寫或是大寫的`f`,接著與第三種呼叫`str.format()`相似,也是用大括號表示要取代的位置,但是他可以直接存取變數的名稱,而不需要再把對應的變數傳入。像這邊,我們可以在`f-string`中存取要顯示的變數`{title}`以及`{timestamp}`,在存取的同時,又可以利用冒號(`:%-m/%d`)來格式化顯示的日期。 ```python= print(f"Title: {title}, Posted on {timestamp:%-m/%d}") ``` ## 我應該要用哪個? 首選是`f-string`,目前大部分的平台都已支援Python3.6+的版本了,`f-string`繼承了前面幾種方法的優點,兼顧程式碼的可讀性,即使是較長的格式化字串,讀者也能一眼就能看出這個位置要替換的目標是哪個變數。更重要的是,`f-string`也是這四種方法裡面,建構字串的速度最快的。 這邊我們分別對四個方法跑一百萬次,看看彼此之間速度的差異。 ```python= import timeit ITERATIONS = 1_000_000 name = "John Doe" age = 30 # + plus_string_elapsed = timeit.timeit(lambda: name + " is " + str(age) + ".", number=ITERATIONS) # Percent string percent_string_elapsed = timeit.timeit(lambda: "%s is %s." % (name, age), number=ITERATIONS) # str.format() str_format_elapsed = timeit.timeit(lambda: "{} is {}.".format(name, age), number=ITERATIONS) # f-string f_string_elapsed = timeit.timeit(lambda: "{name} is {age}.", number=ITERATIONS) result = ( f"plus string: {plus_string_elapsed:.3} s\n" f"percent string: {percent_string_elapsed:.3} s\n" f"str_format: {str_format_elapsed:.3} s\n" f"f-string: {f_string_elapsed:.3} s" ) print(result) ``` 結果 ``` plus string: 0.449 s percent string: 0.373 s str_format: 0.427 s f-string: 0.0897 s ``` ## 後記 對於每個方法更詳細的使用說明以及其中的雷,可以參考我在Colab上的[互動式範例](https://colab.research.google.com/drive/1pZNhX48pTOxv1B9_crGjkO6bzhf7ZQJr?usp=sharing)。