淺析如何在Python中使用結(jié)構(gòu)模式匹配
在Python 3.10中引入的模式匹配語法允許在應(yīng)用程序中使用強大的新編程技術(shù)進行決策。Python雖然功能強大且廣受歡迎,但長期以來缺乏其他語言中的一種流程控制方式,即以一種優(yōu)雅的方式將一個值與多個可能的條件進行匹配。在C和C++中,這是通過構(gòu)造switch/case語句來實現(xiàn)的;在Rust中,這被稱為“模式匹配”。
在Python中,傳統(tǒng)的實現(xiàn)方式并不優(yōu)雅。一種方式是編寫一系列的表達式。另一種方式是將要匹配的值作為字典的鍵存儲起來,然后使用這些值來執(zhí)行相應(yīng)的操作,例如將函數(shù)作為值存儲,并使用鍵或其他變量作為輸入。在許多情況下,這種方式可以很好地工作,但構(gòu)建和維護起來可能會很麻煩,使用if/elif/else語句。
在經(jīng)過多次失敗的提案后,Python語言創(chuàng)始人Guido van Rossum和其他一些貢獻者最近提出的一個提案已被接受,將在Python 3.10中引入結(jié)構(gòu)化模式匹配。結(jié)構(gòu)化模式匹配不僅可以執(zhí)行簡單的樣式匹配,還支持更廣泛的用例。
Python結(jié)構(gòu)化模式匹配
結(jié)構(gòu)化模式匹配引入了語句和模式語法到Python中。該語句遵循與if/elif/else相同的基本概述。它接受一個對象,對該對象進行一項或多項匹配模式的測試,并在找到匹配時執(zhí)行相應(yīng)的操作。
match command:
case "quit":
quit()
case "reset":
reset()
case unknown_command:
print (f"Unknown command '{unknown_command}'")每個語句后面都跟著一個要匹配的模式。 在上面的示例中,我們使用簡單的字符串作為我們的匹配目標(biāo),但更復(fù)雜的匹配也是可能的。事實上,結(jié)構(gòu)化模式匹配的主要用例是匹配類型的模式,而不是值的模式。Python通過從上到下遍歷案例列表來執(zhí)行匹配。在第一個匹配時,Python執(zhí)行相應(yīng)塊中的語句,然后跳到塊的末尾并繼續(xù)執(zhí)行程序的其余部分。在案例之間沒有“穿透”,但可以設(shè)計邏輯來處理單個塊中的多個可能情況。(稍后會詳細介紹)還可以捕獲匹配的全部或部分內(nèi)容并重新使用它。在上面的示例中,如果沒有匹配成功,值將被“捕獲”在變量中,以便我們可以重新使用它。
用Python結(jié)構(gòu)模式匹配對變量進行匹配
這里有一個需要注意的事項。如果在語句中列出變量名,這并不意味著應(yīng)該對命名變量的內(nèi)容進行匹配。在case語句中,變量用于捕獲正在匹配的值。如果想要匹配變量的內(nèi)容,那么該變量必須以點分隔的名稱表示,就像枚舉一樣。以下是一個示例:
from enum import Enum
class Command(Enum):
QUIT = 0
RESET = 1
?
match command:
case Command.QUIT:
quit()
case Command.RESET:
reset()不必使用枚舉;任何點分隔的屬性名稱都可以。但是枚舉通常是在Python中執(zhí)行此操作的最熟悉和慣用的方式。不能通過索引來匹配變量的內(nèi)容。例如,x[0]將被拒絕作為語法錯誤。
使用Python結(jié)構(gòu)化模式匹配進行多個元素的匹配
與模式匹配最有效的工作的關(guān)鍵不僅僅是將其用作字典查找或if/else鏈的替代品。它是描述要匹配的結(jié)構(gòu)的方式。通過這種方式,可以根據(jù)要匹配的元素數(shù)量或它們的組合進行匹配。這里是一個稍微復(fù)雜一些的例子。在這個例子中,用戶輸入一個命令,可選擇性地跟著一個文件名。
command = input("Command:")
match command.split():
case ["quit"]:
quit()
case ["load", filename]:
load_from(filename)
case ["save", filename]:
save_to(filename)
case _:
print (f"Command '{command}' not understood")我們依次來看一下這些情況:
case ["quit"]:測試我們正在匹配的是否是只包含一個元素的列表,該元素是由輸入進行拆分得到的字符串"quit"。case ["load", filename]:測試第一個拆分元素是否是字符串"load",并且是否有一個緊隨其后的字符串。如果是這樣,我們將第二個字符串存儲在變量filename中,并將其用于進一步的操作。case ["save", filename]:與上述情況類似,測試第一個拆分元素是否是字符串"save",并且是否有一個緊隨其后的字符串。如果是這樣,我們將第二個字符串存儲在變量filename中,并將其用于進一步的操作。case _:這是一個通配符匹配。如果到目前為止沒有進行其他匹配,它將匹配。請注意,下劃線變量_實際上不綁定到任何內(nèi)容;該名稱用作命令的信號,表示該情況是一個通配符。(這就是為什么我們在塊的主體中引用該變量;沒有捕獲到任何內(nèi)容。)
在Python中結(jié)構(gòu)模式的匹配模式
模式可以是簡單的值,也可以包含更復(fù)雜的匹配邏輯。以下是一些示例:
case "a":匹配單個值"a"。
case ["a","b"]:匹配集合["a","b"]。
case ["a", value1]:匹配包含兩個值的集合,并將第二個值放入捕獲變量value1中。
case ["a", *values]:匹配至少包含一個值的集合。其他值(如果有)將存儲在values中。請注意,每個集合中只能包含一個星號項(就像在Python函數(shù)中的星號參數(shù)一樣)。
case ("a"|"b"|"c"):使用括號運算符()可以在單個塊中處理多個情況。在這里,我們匹配"a"、"b"或"c"。
case ("a"|"b"|"c") as letter:與上述情況類似,只是現(xiàn)在將匹配的項放入變量letter中。
case ["a", value] if :僅當(dāng)表達式為真時才匹配捕獲??梢栽诒磉_式中使用捕獲變量。例如,如果我們使用value in valid_values,則只有在捕獲的值實際上在集合valid_values中時,才會匹配。
case ["z", _]:以"z"開頭的任何項集合都會匹配。
使用Python結(jié)構(gòu)化模式匹配對對象進行匹配
Python結(jié)構(gòu)化模式匹配系統(tǒng)最高級的功能是能夠針對具有特定屬性的對象進行匹配。考慮一個應(yīng)用程序,我們正在處理一個名為data的對象,我們希望將其轉(zhuǎn)換為文件并從函數(shù)中返回。
match media_object:
case Image(codec="jpg"):
# Return as-is
return media_object
case Image(codec="png") | Image(codec="gif"):
return render_as(media_object, "jpg")
case Video():
raise ValueError("Can't extract frames from video yet")
case other_type:
raise Exception(f"Media object {media_object}
of type {codec} can't be handled yet")在上述每種情況中,我們都在尋找特定類型的對象,有時還具有特定的屬性。第一個情況匹配具有屬性image_codec設(shè)置為"jpg"的對象。第二個情況匹配如果type是"png"或"gif"。第三個情況匹配任何類型為Video的對象,無論其屬性如何。最后一個情況是我們的通配情況,如果其他情況都不匹配,它將捕獲所有對象,盡管我們使用了一個實際的名稱來捕獲它,而不是使用_。我們還可以在對象匹配中進行捕獲:
match media_object:
case Image(codec=media_type):
print (f"Image of type {media_type}")有效地使用Python結(jié)構(gòu)模式匹配
Python結(jié)構(gòu)化模式匹配的關(guān)鍵是編寫能夠覆蓋所要匹配的結(jié)構(gòu)情況的匹配。對常量進行簡單的測試是可以的,但如果只是這樣做,那么簡單的字典查找可能是一個更好的選擇。結(jié)構(gòu)化模式匹配的真正價值在于能夠根據(jù)對象的模式進行匹配,而不僅僅是一個特定的對象或一組對象的選擇。另一個重要的事情是要記住匹配的順序。你首先測試哪些匹配將對整體匹配的效率和準確性產(chǎn)生影響。大多數(shù)構(gòu)建了長鏈的人會意識到這一點,但由于潛在的復(fù)雜性,模式匹配要求你更加仔細地思考順序。將最具體的匹配放在最前面,將最一般的匹配放在最后。最后,如果你的問題可以用簡單的鏈式結(jié)構(gòu)或字典查找來解決,那么請使用它!模式匹配是強大的,但并不是萬能的。在解決問題時,請根據(jù)問題的特點選擇最合適的方法。
到此這篇關(guān)于淺析如何在Python中使用結(jié)構(gòu)模式匹配的文章就介紹到這了,更多相關(guān)Python結(jié)構(gòu)模式匹配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python使用dataframe_image將dataframe表格轉(zhuǎn)為圖片
本文主要介紹了python使用dataframe_image將dataframe表格轉(zhuǎn)為圖片,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
darknet框架中YOLOv3對數(shù)據(jù)集進行訓(xùn)練和預(yù)測詳解
這篇文章主要為大家介紹了darknet框架中YOLOv3對數(shù)據(jù)集進行訓(xùn)練和預(yù)測使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11
使用Python對接OpenAi?API實現(xiàn)智能QQ機器人的方法
這篇文章主要介紹了使用Python對接OpenAi?API實現(xiàn)智能QQ機器人的方法,主要是提供一個方法思路,可以根據(jù)實現(xiàn)代碼延申出更多的解決方法,需要的朋友可以參考下2023-03-03
Python first-order-model實現(xiàn)讓照片動起來
本文將利用first-order-model實現(xiàn)讓照片動起來,除了表情驅(qū)動照片,還可以姿態(tài)遷移。文中的示例代碼講解詳細,感興趣的可以嘗試一下2022-06-06
python斯皮爾曼spearman相關(guān)性分析實例
這篇文章主要為大家介紹了python斯皮爾曼spearman相關(guān)性分析實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
Python中Conda常用命令的超詳細學(xué)習(xí)筆記
Anaconda是一個包含數(shù)據(jù)科學(xué)常用包的Python發(fā)行版本,可以用來安裝和管理不同版本的Python程序包,本文總結(jié)了Anaconda一些常用命令,希望對大家有所幫助2026-06-06
Appium+Python實現(xiàn)簡單的自動化登錄測試的實現(xiàn)
這篇文章主要介紹了Appium+Python實現(xiàn)簡單的自動化登錄測試的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
python獲取微信企業(yè)號打卡數(shù)據(jù)并生成windows計劃任務(wù)
由于公司的系統(tǒng)用的是Java版本,開通了企業(yè)號打卡之后又沒有預(yù)算讓供應(yīng)商做數(shù)據(jù)對接,所以只能自己搗鼓這個,以下是個人設(shè)置的一些內(nèi)容,僅供大家參考2019-04-04

