天天看點

Python 3的f-Strings:增強的字元串格式文法(指南)

最近也在一個視訊網站的爬蟲,項目已經完成,中間有不少需要總結的經驗。

從Python 3.6開始,f-Strings是格式化字元串的一種很棒的新方法。與其他格式化方式相比,它們不僅更具可讀性,更簡潔且不易出錯,而且速度更快!

Python中的“老式”字元串格式化

在Python 3.6之前,你有兩種主要的方式,将Python表達式嵌入到字元串文字中進行格式化:%-formatting和

str.format()

。本文将首先介紹如何使用它們以及它們的局限性。

選項#1:%-formatting

這是Python格式化的OG,從一開始就存在于語言中。你可以在Python文檔中閱讀更多内容。請記住,文檔不建議使用%格式,其中包含以下注意事項:

“這裡描述的格式化操作表現出各種古怪問題,導緻許多錯誤(例如未能正确顯示元組和字典)。

使用較新的格式化字元串文字或

str.format()

方法有助于避免這些錯誤。這些替代方案還提供了更強大,靈活和可擴充的文本格式設定方法。”

如何使用 %-formatting

字元串對象具有使用該

%

運算符的内置操作,可用于格式化字元串。這是實際的情況:

>>> 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字元串格式新手指南》以擷取更多資訊。

如何使用str.format()

str.format() 是對 %-formatting 的改進。它使用正常的函數調用文法,并且可以通過 format() 方法對被轉換為字元串的對象進行擴充。

使用

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()

與%格式相比絕對是一個更新。

為什麼 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-Strings 表達式使格式化更容易。他們加入了Python 3.6。你可以在2015年8月由Eric V.Smith撰寫的PEP 498中閱讀全部内容。

f-Strings 也稱為“格式化的字元串文字”,是一種字元串文字,其開頭是 f,後面是大括号,其中包含将被替換為其值的表達式。這些表達式在運作時被評估,然後使用 "format" 協定進行格式化。當你想了解更多資訊時,Python文檔是你的朋友。

下面是一些 f-strings 可以讓你的生活更輕松的方法。

簡單文法

看看這是多麼容易閱讀:

>>> 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-strings 在運作時被評估,是以您可以在其中放入任何和所有有效的 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-strings的類建立的對象:

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.'
           

__str__()

__repr__()

方法處理對象是如何呈現為字元串,是以你需要確定你包括你的類定義這些方法的至少一個。如果你必須選擇一個,請繼續使用,

__repr__()

因為它可以代替使用

__str__()

傳回的

__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!'
           

如果你想閱讀一些導緻 f-Strings 支援完整Python表達式的對話,則可以在此處進行。

多行f-Strings

你可以使用多行字元串:

>>> 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-Strings 比 %-formatting 和 str.format() 都要快。如你所見,f-Strings 是在運作時求值的表達式,而不是常量值。以下摘自文檔:

“f-Strings 提供了一種使用最小文法在字元串文字中嵌入表達式的方法。應當注意,f-Strings 實際上是在運作時評估的表達式,而不是常數。在Python源代碼中,f-Strings 是文字字元串,字首為

f

,其中花括号内包含表達式。這些表達式将替換為其值。” (來源)

在運作時,大括号内的表達式在其自己的範圍内求值,然後與 f-Strings 的字元串文字部分放在一起。然後傳回結果字元串。這就是全部。

這是速度比較:

>>> 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-Strings 最快。

但是,情況并非總是如此。首次實施時,它們存在一些速度問題,需要使其速度比更快

str.format()

。引入了特殊的

BUILD_STRING

操作碼。

Python f-Strings:細節

既然你已經了解了為什麼 f-Strings 很棒,我相信你一定要開始使用 f-Strings 。當你冒險進入這個勇敢的新世界時,請牢記以下一些細節。

引号

你可以在表達式内使用各種類型的引号。隻要確定你沒有在表達式中使用與 f-Strings 相同的引号即可。

該代碼将起作用:

>>> 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-Strings 使用雙引号。

這将起作用:

>>> 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 "<stdin>", line 1
    f'The comedian is {comedian['name']}, aged {comedian['age']}.'
                                    ^
SyntaxError: invalid syntax
           

如果在字典鍵周圍使用與在f字元串外部相同的引号類型,則第一個字典鍵開頭的引号将被解釋為字元串的結尾。

大括号

為了使大括号出現在字元串中,必須使用雙大括号:

>>> f"{{70 + 4}}"
'{70 + 4}'
           

請注意,使用三重花括号将導緻字元串中隻有一個大括号:

>>> f"{{{70 + 4}}}"
'{74}'
           

但是,如果使用的括号多于三個,則可以顯示更多的括号:

>>> f"{{{{70 + 4}}}}"
'{{70 + 4}}'
           

反斜杠

如前所述,你可以在f-string的字元串部分使用反斜杠轉義。但是,你不能在f-string的表達式部分使用反斜杠轉義:

>>> f"{\"Eric Idle\"}"
  File "<stdin>", 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 "<stdin>", line 1
    f"Eric is {2 * 37 #Oh my!}."
                                ^
SyntaxError: f-string expression part cannot include '#'
           

總結

字元串格式化方法在很多項目裡面都能用到,實用價值很高。

請訂閱并繼續關注,以後會收到更多有趣的文章。

歡迎關注我的個人網站https://www.bianchengvip.com/

本文為“一個火星程式員”原創文章,轉載請标明出處