第一篇技術文章就決定是你了(笑)

PEP 498: Formatted string literals

Formatted string literals,我暫時翻譯成格式化字串實字,是 Python 在 3.6 版加入的新特色,這個功能源自於 PEP 中的 498 號提案,而這個特色又被稱作 f-string,讓我們來看看要怎麼使用吧:

name = 'Sky'
print(f'My name is {name}.')
# 'My name is Sky.'

有看到單引號前的 f 嗎?那是表示這個字串中會包含需要被取代的部分(F 也可以),然後讓我們看看字串中間的左大括號,這是取代欄位的開始,右大括號則是標示出了這個欄位的結束。

Replacement field 取代欄位

在這個欄位中,基本上可以放入任何 Python表示式,甚至包含 lambda 函式:

myNumber = 5
print(f'''My number is a 
{(lambda n: "Lucky" if n % 3 == 0 else "Unlucky")(myNumber)} number.''')
# My number is a 
# Unlucky number.

需要注意的是:lambda 主體需要以 () 小括號包住,否則會引起 SyntaxError 例外;這裡同時展現了 f-string 另一個特色:可以像我們平常使用字串時那樣以三個引號表達多行字串,同樣地,任何空白字元都會被包起來,成為字串的一部分。

小問題

如果你寫了一行這樣的程式碼:

print(f'"{" is a opening curly bracket.')

會發現說引起了 SyntaxError 例外,為什麼呢?

#   File "<stdin>", line 1
# SyntaxError: f-string: unterminated string

應該很淺顯易懂,左大括號代表的是一個欄位的起點,所以上述的例子中,Python直譯器會找不到代表結束的右大括號。

那如果字串中需要一個真正的左 / 右大括號呢? 可以使用 {{}},將兩個大括號連在一起:

print(f'"{{" is a opening curly bracket.')
# "{" is a opening curly bracket.

Conversion field 轉換欄位

轉換欄位以 ! 作為開始:

import datetime
print(f'The time now is {datetime.datetime.now()}.')
# The time now is 2017-01-24 22:48:13.117520.
print(f'The time now is {datetime.datetime.now()!r}.')
# The time now is datetime.datetime(2017, 1, 24, 22, 48, 19, 414828).

轉換欄位的位置在於取代欄位中,要被轉換的表示式(變數)後面,共有 !a!r!s 三種轉換欄位。

  1. !a 代表對整個取代結果使用 ascii() 函式
  2. !r 則是 repr()
  3. !s 當然就是 str()

巢狀欄位

其實正式上來說也不算是巢狀欄位啦,就像 string.format() 方法一樣,你可以指定取代後的格式,例如說:

from decimal import Decimal
value = Decimal('89.65432')
allWidth = 10
precision = 3
print(f'value:{value:{allWidth}.{precision}}')
# value:      89.7

如果是浮點數的話他會幫你四捨五入。

小問題-2

在取代欄位中,不能有反斜線 \,就算用 r 包起來也一樣:

print(f"newline: {ord('\n')}")
# SyntaxError: f-string expression part cannot include a backslash

newline = ord('\n')
print(f"newline: {newline}")
# newline: 10