python進階用法2 【從幫助函式看python記憶體申請機制】
前言
介紹了四個幫助函式,dir()
,help()
,type()
,id()
,通過id()函式進一步分析了python在申請記憶體方面的效率問題,提到的基本型別有string
,list
,queue
和deque
四個幫助函式
dir()函式
dir()函式是檢視函式或模組內的操作方法都有什麼,輸出的是方法列表。
dir('str')
也可以檢視自己定義的函式
help()函式
help()函式是檢視函式或模組用途的詳細說明,例:
help('str')
type()函式
這個很簡單了,返回其型別,略
id()函式
對一個物件的引用呼叫id()
id()
值.
PS: 在CPython
實現細節:識別符號(dentity)為物件在記憶體中的地址. 在Python
中一切皆物件,變數中存放的是物件的引用.字串常量和整型常量都是物件.
舉個例子:
>>> a = 1
>>> b=2
>>> c =1
>>> id(a)
1521120064
>>> id(b)
1521120096
>>> id(c)
1521120064
不知道,在看這個dentity
的時候,有沒有發現a與c的地址是相同的!!!
從id()函式看python記憶體地址申請機制
如果還是沒有理解的話,接下來看我本地進行的一個非常簡單的一個演示指令碼測試:
import time
t1 = time.time()
astr = 'a'
for x in range(1,2000000):
astr = astr + str(x)
astr
t2 = time.time()
print(t2-t1)
#10.028913259506226
#[Finished in 10.2s]
import time
t1 = time.time()
astr = list('1'*2000000)
for x in range(1,2000000):
astr[x]=str(x)
bstr = str(astr)
t2 = time.time()
print(t2-t1)
#0.8323781490325928
#[Finished in 1.1s]
為什麼差距如此之大呢?這就回到了我們最初提到的a
,b
,當值改變,會重新去申請記憶體空間(id改變)。在這第一個例子中,我們不停地改變astr
的值,astr
即不停地申請記憶體空間,此過程消耗了大量的時間!!!第二個例子中,我們一次申請了夠所有變數使用的記憶體空間地址,免去了每次申請,所以大大加快了執行速度!!!
感謝@一個閒散之人的閒散
更進一步的分析,
影響其效率問題的核心根本在於list
到底是基於連結串列的資料結構還是基於線性表的資料結構。線性表的話為了騰出足夠連續空間需要改變表頭的記憶體位置,也就造成了id
的改變,對於連結串列而言,則只需要申請一個結點大小的記憶體量,沒必要對錶頭的記憶體位置動手腳。
關於list
的資料結構,從知乎上get到的結果是線性表形式的資料結構,於是乎我又做了以下3個測試:
1、不提前申請空間的queue
import time
import queue
t1 = time.time()
astr = queue.Queue()
for x in range(1,2000000):
astr.put(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 4.525705337524414
# [Finished in 4.8s]
2、不提前申請空間的deque
import collections
import time
t1 = time.time()
astr = collections.deque()
for x in range(1,2000000):
astr.append(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 0.938164234161377
# [Finished in 1.3s]
3、不提前申請空間的list
import time
t1 = time.time()
astr = []
for x in range(1,2000000):
astr.append(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 0.9456796646118164
# [Finished in 1.2s]
另做個測試:
import collections
import queue
print("Deque ID:")
astr1 = collections.deque()
for x in range(1,5):
astr1.append(str(x))
print(id(astr1))
print("Queue ID:")
astr2 = queue.Queue()
for x in range(1,5):
astr2.put(str(x))
print(id(astr2))
print("list ID:")
astr3 = []
for x in range(1,5):
astr3.append(str(x))
print(id(astr3))
# Deque ID:
# 1206229307464
# 1206229307464
# 1206229307464
# 1206229307464
# Queue ID:
# 1206225595416
# 1206225595416
# 1206225595416
# 1206225595416
# list ID:
# 1206229266760
# 1206229266760
# 1206229266760
# 1206229266760
# [Finished in 0.2s]
queue
、deque
其實可以很明顯看出,其均是依靠c的連結串列
進行開發的(不需要提前申請空間),其地址亦不變化。更改一點之前的錯誤理解,python的list
實現不是連結串列,而是動態陣列
當我們使用deque
時,可以很明顯看到,我們的時間消耗已經差距很小了,與未提前申請空間的list
接近一致,但經多次執行,還是可以發現,最快的依舊是已經申請了空間的list
,我麼進一步去了解queue
和deque
可以發現其無法提前申請空間(可以理解為其職能分別從一端和兩段進行增加值,減值),及無法像list
一樣可以通過list[下標]
直接取值,所以綜上所述,list無疑是最快的~
補充,list的擴張空間機制
>>> test = []
>>> test.__sizeof__()
40
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
104
>>>
相關推薦
python進階用法2 【從幫助函式看python記憶體申請機制】
前言 介紹了四個幫助函式,dir(),help(),type(),id(),通過id()函式進一步分析了python在申請記憶體方面的效率問題,提到的基本型別有string,list,queue和deque 四個幫助函式 dir()函式 dir(
python進階(2)——re模組:正則表示式1
實驗結果輸出文件,包括多項引數(大約幾百個),想把所有的loss value對應的值提取出來,畫出曲線圖,這就需要用到正則表示式,基於此,開始學習正則表示式。 正則表示式:可匹配文字片段的模式 萬用字元:句點.(.ython與jpython與python與 ython都匹配,但不與ython
python進階(2)——re模組:正則表示式2
re.split 根據模式來分割字串 import re text='a, b,,,,c d' print(re.split('[, ]+', text)) #re.split:以空格和字串分割字元 re.findall 返回列表,包含所有與給定模式匹配的子串 import re
Python 進階用法 (持續更新)
裝飾器(Decorator) Python 的裝飾器是任何可呼叫物件(callable object),用於修改函式(Function)或類(Class)。按照用途可分為: 函式裝飾器 類裝飾器 裝飾器的介面定義可概括為: 接收某個函式或類的引用作為引數; 修改該函式或類並返回
python進階—OpenCV之常用影象操作函式說明
文章目錄 cv2.threshold cv2.bitwise_and cv2.bitwise_or cv2.bitwise_not cv2.inRange cv2.resize cv2.adaptiveThreshold cv2
Python進階丨如何建立你的第一個Python元類?
摘要:通過本文,將深入討論Python元類,其屬性,如何以及何時在Python中使用元類。 Python元類設定類的行為和規則。元類有助於修改類的例項,並且相當複雜,是Python程式設計的高階功能之一。通過本文,將深入討論Python元類,其屬性,如何以及何時在Python中使用元類。本文介紹以下概念:
Python自動化開發課堂筆記【Day08】 - Python進階(面向對象的高級用法,網絡編程)
sta 自然 log 報錯 面向 read urn total 析構函數 面向對象的高級用法 1. __str__ 只要執行打印對象的操作,就會觸發該對象類中的__str__方法(也就是對象的綁定方法)它是一種默認的方法,默認的打印輸出為<__main__.Foo o
【python進階】map, filter, reduce用法
map map會將一個函式對映到一個輸入列表的所有元素上面。 map(function_to_apply, list_of_inputs) map可以讓我們用一種簡單而漂亮得多的方式來實現。 items = [1,2,3,4,5] squared = lis
【python進階】*args 和 **kwargs的用法
參考連結:https://eastlakeside.gitbooks.io/interpy-zh/content/args_kwargs/Usage_args.html 變數名不是最重要的,前面兩個*才是最重要的。 *args用法 *args用來發送一個非鍵值對的可變數量的引
Python自動化開發課堂筆記【Day06】 - Python進階(類)
擴展性 程序 lex 類名 人物 優點 ini 參數 self. 類與對象 面向過程的程序設計: 優點:極大的降低了程序的復雜度 缺點:一套流水線或者流程就是用來解決一個問題,生產汽水的流水線無法生產汽車,即使能,也是得大改,改一個組件,牽一發而動全身面向對象的程序設計
Python進階----*args和**kwargs,裝飾器的用法
pop reference value -- margin zoj 是什麽 ec2 多線程 關於多線程的一個問題 svn提交代碼的時間是什麽時候? 大家都開始C++0x了,我也來湊熱鬧,今天的主題是《調侃rvalue-reference》 新手c語言,求助break問
Python初學者第二十三天 函數進階(2)裝飾器
分享 username 執行 ... ret 傳參 als print n) 23day 裝飾器: 1、用戶不執行前不調用函數,在調用的時候再執行函數 a、傳函數時不加參數 user_status = False # 用戶登錄了就把這個改成True def login(
python之函數的進階(2-1)
加載 gif pre span 進行 文件 chang ret 16px 動態參數: 一,*args:args是元祖,它包含了所有的位置參數。 1,第一種形參中只含*args。 def func(*args): print(*args,type(args)) f
【學習筆記】python 進階特性
可能 pytho red nbsp python blog 有一個 自省 blue __slots__魔法 在Python中,每個類都有實例屬性。默認情況下Python用一個字典來保存一個對象的實例屬性。這非常有用,因為它允許我們在運行時去設置任意的新屬性。 然而,對於有
Python進階【第一篇】:Python簡介
代碼 簡潔 處理 ros 進一步 基礎 得到 運行速度 動態 Python簡介 1.Python的由來 Python是著名的“龜叔”Guido van Rossum在1989年聖誕節期間,為了打發無聊的聖誕節而編寫的一個編程語言。 2.C 和 Python、Java、C#等
Python進階【第九篇】裝飾器
turn spa none app light fun rap log python 什麽是裝飾器 裝飾器本身就是函數,並且為其他函數添加附加功能 裝飾器的原則:1.不修改被裝飾對象的源代碼 2.不修改被裝飾對象的調用方式裝飾器=高階函數+函數嵌套+閉包 # res=t
Python進階【第十篇】模塊(上)
path 變量 屬性 一個 第三方 sys pre 應用程序 bsp ·一、模塊 模塊就是一組功能的集合體,我們的程序可以導入模塊來復用模塊裏的功能。為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件裏,這樣,每個文件包含的代碼就相對較少,很多編程語言都采用這種組
Python進階-----property用法(實現了get,set,delete三種方法)
一、可以利用property對靜態屬性的進行修改操作,包括設定和刪除屬性 1、呼叫靜態屬性===>在靜態屬性函式前先用@property; 2、設定靜態屬性===>在靜態屬性函式前加上@靜態屬性函式名.setter,同時靜態屬性函式要加上value引數; 3、刪除靜態屬性===>
python進階(lxml的用法)
本節處理的檔案如下,檔名為:webhtml.html <!DOCTYPE html> <html> <head> <
python進階(爬蟲 BeautifulSoup用法)
操作演示檔案: 檔名: webhtml.html <!DOCTYPE html> <html> <head> <title>漏斗圖</title> <script type="