7. 輸入和輸出

有數種方式可以顯示程式的輸出;資料可以以人類易讀的形式印出,或是寫入檔案以供未來所使用。這章節會討論幾種不同的方式。

7.1. 更華麗的輸出格式

目前為止我們已經學過兩種寫值的方式:運算式陳述 (expression statements)print() 函式。(第三種方法是使用檔案物件的 write() 方法;標準輸出的檔案是使用 sys.stdout 來達成的。詳細的資訊請參考對應的函式庫說明。)

通常你會想要對輸出格式有更多地控制,而不是僅列印出以空格隔開的值。以下是幾種格式化輸出的方式。

  • 要使用格式化字串文本 (formatted string literals),需在字串開始前的引號或連續三個引號前加上 fF。你可以在這個字串中使用 {} 包夾 Python 的運算式,引用變數或其他字面值 (literal values)。

    >>> year = 2016
    >>> event = 'Referendum'
    >>> f'Results of the {year} {event}'
    'Results of the 2016 Referendum'
    
  • 字串的 str.format() method 需要更多手動操作。你還是可以用 {} 標示欲替代變數的位置,且可給予詳細的格式指令,但你也需提供要被格式化的資訊。在以下程式碼區塊中,有兩個如何格式化變數的範例:

    >>> yes_votes = 42_572_654
    >>> total_votes = 85_705_149
    >>> percentage = yes_votes / total_votes
    >>> '{:-9} YES votes  {:2.2%}'.format(yes_votes, percentage)
    ' 42572654 YES votes  49.67%'
    

    請注意 yes_votes 如何對於負數用空格和負號填補。該範例還會列出 percentage 乘以 100,並保留 2 位小數且後面跟著一個百分號(有關詳細資訊,請參閱 格式規格 (Format Specification) 迷你語言)。

  • 最後,你還可以自己用字串切片 (slicing) 和串接 (concatenation) 操作,完成所有的字串處理,建立任何你能想像的排版格式。字串型別有一些 method,能以給定的欄寬填補字串,這些運算也很有用。

如果你不需要華麗的輸出,只想快速顯示變數以進行除錯,可以用 repr()str() 函式把任何的值轉換為字串。

str() 函式的用意是回傳一個人類易讀的表示法,而 repr() 的用意是產生直譯器可讀取的表示法(如果沒有等效的語法,則造成 SyntaxError)。如果物件沒有人類易讀的特定表示法,str() 會回傳與 repr() 相同的值。有許多的值,像是數字,或 list 及 dictionary 等結構,使用這兩個函式會有相同的表示法。而字串,則較為特別,有兩種不同的表示法。

一些範例:

>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1/7)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # 字串的 repr() 會加上字串引號和反斜線:
>>> hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # repr() 的引數可以是任何 Python 物件:
>>> repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

string 模組包含一個基於正規表示式 (regular expressions)、透過 string.Template 的簡單模板化手段的支援。這提供了另一種將值替換到字串中的方式,使用像 $x 這樣的佔位符號,並用來自字典的值取代它們。這種語法較易用,但它在格式化方面提供的控制較少。

7.1.1. 格式化的字串文本 (Formatted String Literals)

格式化的字串文本(簡稱為 f-字串),透過在字串加入前綴 fF,並將運算式編寫為 {expression},讓你可以在字串內加入 Python 運算式的值。

格式說明符 (format specifier) 是選擇性的,寫在運算式後面,可以更好地控制值的格式化方式。以下範例將 pi 捨入到小數點後三位:

>>> import math
>>> print(f'The value of pi is approximately {math.pi:.3f}.')
The value of pi is approximately 3.142.

':' 後傳遞一個整數,可以設定該欄位至少為幾個字元寬,常用於將每一欄對齊。

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print(f'{name:10} ==> {phone:10d}')
...
Sjoerd     ==>       4127
Jack       ==>       4098
Dcab       ==>       7678

還有一些修飾符號可以在格式化前先將值轉換過。'!a' 會套用 ascii()'!s' 會套用 str()'!r' 會套用 repr()

>>> animals = 'eels'
>>> print(f'My hovercraft is full of {animals}.')
My hovercraft is full of eels.
>>> print(f'My hovercraft is full of {animals!r}.')
My hovercraft is full of 'eels'.

= 說明符可用於將一個運算式擴充為該運算式的文字、一個等號、以及對該運算式求值 (evaluate) 後的表示法:

>>> bugs = 'roaches'
>>> count = 13
>>> area = 'living room'
>>> print(f'Debugging {bugs=} {count=} {area=}')
Debugging bugs='roaches' count=13 area='living room'

更多關於 = 說明符的資訊請見自文件性運算式 (self-documenting expressions)。若要參考這些格式化字串的規格,詳見 格式規格 (Format Specification) 迷你語言 參考指南。

7.1.2. 字串的 format() method

str.format() method 的基本用法如下: