10、Python之寫出更加Pythonic的代碼:unpacking拆包機制

引言

有些小伙伴有其他編程語言的學習、使用的經驗,然后遷移到Python。一般會比完全的新手小白,更快速地把Python用起來。這是他們的優勢,但也是他們的劣勢。
之所以這么說,是因為從其他編程語言帶過來的,除了相通的編程思維、框架性的東西,還有編程語言的使用習慣。
而這些其他編程語言中的使用習慣,就會導致他們寫出來的Python代碼不是那么的Pythonic,當然,這是一種感覺。
雖說我們首要追求的是能用、夠用。但是,偶爾也要稍微留意一下。就好像學習英語一樣,雖然不追求能操著一口正宗的英倫腔,但也不應該對自己的chinglish迷之自信。
此外,故步自封于其他編程語言中的編程習慣,也可能限制我們更加靈活、便捷地發揮Python中的強大特性。

變量值交換

其他語言中,如果需要交換兩個變量,通常需要引入一個中間變量,比如:

a = 5
b = 10
c = b
b = a
a = c

在Python中還這樣寫,就顯得有些冗余、不夠地道了。
其實,在Python中有一種更加簡便的寫法:

x = 5
y = 10
x, y = y, x

不需要引入中間變量,直接完成變量值的交換。我看有些地方把Python中的這種變量值交換,稱之為unpacking機制。所以,我在今天的這篇講解unpacking機制的文章中提到了這一點。

但是,也許是Python不同版本、Python解釋器實現的差異,在我的Python3.11、CPython解釋器的環境下,查看對應的字節碼,發現并沒有用到unpacking機制,而是Python中提供了一個用于進行棧頂兩個值交換的swap指令。對應的字節碼指令及解釋,如下圖所示:感興趣的可以自行查看自己環境中變量值交換的實現。

基礎unpacking機制

接下來,說回今天的主題,unpacking機制。
既然是unpacking,有些地方翻譯為拆包,自然首先要有包可拆。這里所謂的拆包,其實是針對容器/集合類型的數據結構來說的。

通常情況下,我們把一個列表、元組或者是字典中的元素取出來,可以使用下標索引的方式。
比如,有如下場景:
我們有一些人員信息存放在一個列表中,每個列表元素是一個元組,元組中的元素,分別是姓名、年齡、性別。
現在,我們需要遍歷人員信息的這個列表,然后將人員信息進行格式化打印輸出。
使用下標索引的方式,可以這樣實現:

persons = [('張三', 18, '女'), ('小紅', 23, '男')]
for p in persons:name = p[0]age = p[1]gender = p[2]print(f"姓名: {name}, 年齡: {age}, 性別: {gender}")

但是,這樣的寫法,不夠地道,沒有使用Python給我們提供的更加好用的寫法。
接下來,我們用unpacking的方式重新寫一下:

# unpacking
persons = [('張三', 18, '女'), ('小紅', 23, '男')]
for p in persons:name, age, gender = pprint(f"姓名: {name}, 年齡: {age}, 性別: {gender}")

這樣寫下來,用到了Python中的unpacking,首先代碼行數減少了。
是否真的應用到了unpacking機制,還是說跟變量值交換一樣,也是人云亦云,我們可以看下對應的字節碼序列:

字節碼指令序列的其他指令可以不用關心,我們重點看源碼第4行的對應指令序列,可以看到:
1、確實觸發了unpacking機制;
2、UNPACK_SEQUENCE指令,用于將棧頂的集合變量進行拆包的操作,拆為多少個,指令有一個操作數,此時是3,由操作數決定;
3、拆包指令實現的結果是,棧頂集合變量出棧,按照操作數拆分,然后依次入棧。

unpacking的機制,看似好用,但是,細心的你,可能立馬會發現一個問題,如果集合中元素有很多個,此時,我們只需要其中的一部分,怎么辦呢。

解決的方法,就是我們在前面的文章中提到過的占位符_的用法。
比如,我們當前,只需要姓名、性別,可以這樣改寫:

# unpacking
persons = [('張三', 18, '女'), ('小紅', 23, '男')]
for p in persons:name, _, gender = pprint(f"姓名: {name}, 性別: {gender}")

所有我們不需要的元素,都可以用占位符進行舍棄,但是,占位符_只是省去了我們給變量取名的麻煩,不需要的元素比較多的時候,似乎還是不太方便,反而不如索引操作方便,好在Python中提供了對應的解決方案。

擴展的unpacking

的變量,在Python中為可擴展的變量。
如下,為帶
的unpacking的寫法:

# * unpacking
persons = [('張三', 18, 190, '女'), ('小紅', 23, 165, '男')]
for p in persons:name, *others, gender = pprint(others)print(type(others))print(f"姓名: {name}, 性別: {gender}")

代碼中,會將除了name接收的第一個元素,以及gender接收的最后一個元素,之外的所有元素,封裝為一個列表,由others接收。
從對應的字節碼,可以看出有些不同:

首先,翻譯為字節碼指令序列時,多了EXTENDED_ARG指令,用于擴展變量others;其次拆包的指令,從之前的UNPACK_SEQUENCE變成了UNPACK_EX。

注意,關于帶星號定義的可擴展變量,可以理解為不定長列表,可以接收零個或者多個值,后續在函數的定義中也會用到。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43769.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43769.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43769.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MOJO語言中的字典和哈希表:數據結構的靈活性與效率

MOJO是一種編程語言,它以其獨特的語法和對現代編程范式的支持而聞名。在MOJO中,字典(也稱為哈希表或散列表)是一種非常重要的數據結構,它允許開發者以鍵值對的形式存儲和檢索數據。本文將深入探討MOJO語言中的字典和哈…

第十八節 LLaVA如何按需構建LORA訓練(視覺、語言、映射多個組合訓練)

文章目錄 前言一、基于llava源碼構建新的參數1、添加lora_vit參數2、訓練命令腳本設置二、修改源碼,構建lora訓練1、修改源碼-lora訓練2、LLM模型lora加載3、VIT模型加載4、權重凍結操作5、結果顯示三、實驗結果前言 如果看了我前面文章,想必你基本對整個代碼有了更深認識。…

Raylib 實現超大地圖放大縮小與兩種模式瓦片地圖刷新

原理: 一種刷新模式: 在宮格內整體刷新,類似九宮格移動到邊緣,則九宮格整體平移一個宮格,不過這里是移動一個瓦片像素,實際上就是全屏刷新,這個上限是 筆記本 3060 70幀 100*100個瓦片每幀都…

數據庫之MQL

1,查詢所有 mysql> select * from grade;2, mysql> select id,firstname,lastname from grade;3, mysql> select firstname,lastname from grade where id > 4;4, mysql> select * from grade where sex f;5&…

C++中的函數指針

C中的函數指針 在C中,函數指針是一個指向函數的指針,可以用來調用函數。函數指針的聲明方式如下: 返回類型 (*指針變量名)(參數列表);例如,如果有一個函數: int add(int a, int b) {return a b; }可以聲明一個指向…

微服務通信新紀元:Eureka與分布式服務網格的融合

微服務通信新紀元:Eureka與分布式服務網格的融合 引言 在微服務架構中,服務間的通信是構建分布式系統的核心。Eureka作為Netflix開源的服務發現框架,提供了服務注冊與發現的功能,而服務網格技術則為服務間通信提供了更細粒度的控…

Hive/Spark窗口函數

窗口函數 hive文檔鏈接 spark文檔鏈接 1. OVER支持的函數 自然序編號 Syntax: ROW_NUMBER按等級編號 Syntax: RANK | DENSE_RANK | PERCENT_RANK分組內分桶,并返回對應桶的序號 Syntax: NTILE(n)Analytic Functions(分析函數) Syntax: CUM…

odoo17 常見升級問題

通用問題 模型名變更 字段變更 方法名變更 方法參數變更 xml數據結構定義變化 xml的id變更 view視圖變化,導致xpath路徑出差 template結構變化,,導致xpath路徑出差,或者id不存在 升16問題 前端owl的架構變化 升17問題 前端 標…

什么,有狗快跑!慢著,這次手把手教你怎么過安全狗!(sql注入篇)

前言 在記憶里上次繞安全狗還是在上次,開開心心把自己之前繞過狗的payload拿出來,發現全部被攔截了,事情一下子就嚴肅起來了,這就開整。 環境 本次環境如下sqli-lab的sql注入靶場 網站安全狗APACHE版V4.0版本的最高防護等級繞過…

秋招Java后端開發沖刺——并發篇2(ThreadLocal、Future接口)

本文對ThreadLocal類和Future接口進行了總結概括,包括ThreadLocal類的原理、內存泄露等問題,和Future接口的使用等問題。 一、ThreadLocal 1. 介紹 ThreadLocal(線程局部變量)是Java中的一個類,線程通過維護一個本地…

一文帶你徹底搞懂什么是責任鏈模式!!

文章目錄 什么是責任鏈模式?詳細示例SpingMVC 中的責任鏈模式使用總結 什么是責任鏈模式? 在我們日常生活中,經常會出現一種場景:一個請求需要經過多個對象的處理才能得到最終的結果。比如,一個請假申請,需…

STM32智能倉庫管理系統教程

目錄 引言環境準備智能倉庫管理系統基礎代碼實現:實現智能倉庫管理系統 4.1 數據采集模塊 4.2 數據處理與控制算法 4.3 通信與網絡系統實現 4.4 用戶界面與數據可視化應用場景:倉庫管理與優化問題解決方案與優化收尾與總結 1. 引言 智能倉庫管理系統通…

藏漢翻譯通作為翻譯軟件的優勢有哪些?

藏漢翻譯通作為一款專業的藏漢雙語翻譯軟件,具有以下優勢: 人工智能技術應用:藏漢翻譯通利用了人工智能翻譯和語音識別合成技術,提供智能藏文翻譯服務。 高準確率:文字識別準確率可達90%,語音識別轉化文字…

蒼穹外賣--導入分類模塊功能代碼

把各層代碼拷貝到所需文件夾下, 進行編譯 在運行 提交和推送倉庫

解鎖AI大模型潛能:預訓練、遷移學習與中間件編程的協同藝術

在人工智能的浩瀚星空中,大型預訓練模型(Large Language Models, LLMs)猶如璀璨的星辰,引領著技術革新的浪潮。這些模型通過海量數據的滋養,學會了理解語言、生成文本乃至執行復雜任務的能力。然而,要讓這些…

【正點原子i.MX93開發板試用連載體驗】項目計劃和開箱體驗

本文最早發表于電子發燒友:【   】【正點原子i.MX93開發板試用連載體驗】基于深度學習的語音本地控制 - 正點原子學習小組 - 電子技術論壇 - 廣受歡迎的專業電子論壇! (elecfans.com)https://bbs.elecfans.com/jishu_2438354_1_1.html 有一段時間沒有參加電子發…

Pyspider WebUI 未授權訪問致遠程代碼執行漏洞復現

0x01 產品簡介 Pyspider是由國人binux編寫的強大的網絡爬蟲系統,它帶有強大的WebUI(Web用戶界面),為用戶提供了可視化的編寫、調試和管理爬蟲的能力。這一特點使得Pyspider在爬蟲框架中脫穎而出,尤其適合那些希望快速上手并高效開發爬蟲的用戶。允許用戶直接在網頁上編寫…

for in和for of對比

不同點: 時間點不同:for in 在js出現之初就有,for of出現在ES6之后 遍歷的內容不同:for in用于遍歷對象的可枚舉屬性(包括原型鏈上的可枚舉屬性),for of用于遍歷可迭代對象的值 看個例子 // for in const arr [a,b,…

Linux--線程的控制

目錄 0.前言 1.pthread庫 2.關于控制線程的接口 2.1.創建線程(pthread_create) 2.2.線程等待(pthread_join) 代碼示例1: ?編輯 ***一些問題*** 2. 3.創建多線程 3.線程的終止 (pthread_exit /…

給數組/對象添加一個(key-value)對象

需要將一個value值前面加上key值,放進數組/對象中 this.$set(res.data[0],type,1) this.$set( target, key, value ) target:要更改的數據源(可以是對象或者數組) key:要更改的具體數據 value :重新賦的值。 結果:…