在 Python 中,有四類最常見的內建容器類型:
列表(list)
、
元組(tuple)
、
字典(dict)
、
集合(set)
。通過單獨或是組合使用它們,可以高效的完成很多事情。
Python 語言自身的內部實現細節也與這些容器類型息息相關。比如 Python 的類實例屬性、全局變量
globals()
等就都是通過字典類型來存儲的。
在這篇文章里,我首先會從容器類型的定義出發,嘗試總結出一些日常編碼的最佳實踐。之后再圍繞各個容器類型提供的特殊機能,分享一些編程的小技巧。
當我們談論容器時,我們在談些什么?
我在前面給了“容器”一個簡單的定義:專門用來裝其他對象的就是容器。但這個定義太寬泛了,無法對我們的日常編程產生什么指導價值。要真正掌握 Python 里的容器,需要分別從兩個層面入手:
-
底層實現: 內置容器類型使用了什么數據結構?某項操作如何工作?
- 高層抽象: 什么決定了某個對象是不是容器?哪些行為定義了容器?
下面,讓我們一起站在這兩個不同的層面上,重新認識容器。
底層看容器
Python 是一門高級編程語言, 它所提供的內置容器類型,都是經過高度封裝和抽象后的結果。 和“鏈表”、“紅黑樹”、“哈希表”這些名字相比,所有 Python 內建類型的名字,都只描述了這個類型的功能特點,其他人完全沒法只通過這些名字了解它們的哪怕一丁點內部細節。
這是 Python 編程語言的優勢之一。相比 C 語言這類更接近計算機底層的編程語言,Python 重新設計并實現了對編程者更友好的內置容器類型,屏蔽掉了內存管理等額外工作。為我們提供了更好的開發體驗。
但如果這是 Python 語言的優勢的話,為什么我們還要費勁去了解容器類型的實現細節呢?答案是: 關注細節可以幫助我們編寫出更快的代碼。
如果你依然在編程的世界里迷茫,可以加入我們的Python學習扣qun:784758214,看看前輩們是如何學習的。交流經驗。從基礎的python腳本到web開發、爬蟲、django、數據挖掘等,零基礎到項目實戰的資料都有整理。送給每一位python的小伙伴!分享一些學習的方法和需要注意的小細節,點擊加入我們的 python學習者聚集地
寫更快的代碼
1. 避免頻繁擴充列表/創建新列表
所有的內建容器類型都不限制容量。如果你愿意,你可以把遞增的數字不斷塞進一個空列表,最終撐爆整臺機器的內存。
在 Python 語言的實現細節里,列表的內存是按需分配的[注1],當某個列表當前擁有的內存不夠時,便會觸發內存擴容邏輯。而分配內存是一項昂貴的操作。雖然大部分情況下,它不會對你的程序性能產生什么嚴重的影響。但是當你處理的數據量特別大時,很容易因為內存分配拖累整個程序的性能。
還好,Python 早就意識到了這個問題,并提供了官方的問題解決指引,那就是: “變懶” 。
如何解釋“變懶”?
range()
函數的進化是一個非常好的例子。
在 Python 2 中,如果你調用
range(100000000)
,需要等待好幾秒才能拿到結果,因為它需要返回一個巨大的列表,花費了非常多的時間在內存分配與計算上。但在 Python 3 中,同樣的調用馬上就能拿到結果。因為函數返回的不再是列表,而是一個類型為
range
的懶惰對象,只有在你迭代它、或是對它進行切片時,它才會返回真正的數字給你。
所以說,為了提高性能,內建函數
range
“變懶”了。
而為了避免過于頻繁的內存分配,在日常編碼中,我們的函數同樣也需要變懶,這包括:
-
更多的使用
yield
關鍵字,返回生成器對象 -
盡量使用生成器表達式替代列表推導表達式
-
生成器表達式:
(iforinrange(100))
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
