1、Python是如何進行bai記憶體管理du的?
Python的記憶體管理主要有三種機制:引用計數zhi機制、垃圾回收dao機制和記憶體池機制。
a. 引用計數
當給一個物件分配一個新名稱或者將一個物件放入一個容器(列表、元組或字典)時,該物件的引用計數都會增加。
當使用del對物件顯示銷燬或者引用超出作用於或者被重新賦值時,該物件的引用計數就會減少。
可以使用sys.getrefcount()函式來獲取物件的當前引用計數。多數情況下,引用計數要比我們猜測的大的 多。對於不可變資料(數字和字串),直譯器會在程式的不同部分共享記憶體,以便節約記憶體。
b. 垃圾回收
當一個物件的引用計數歸零時,它將被垃圾收集機制處理掉。
當
兩個物件a和b相互引用時,del語句可以減少a和b的引用計數,並銷燬用於引用底層物件的名稱。然而由於每個物件都包含一個對其他物件的應用,因此引用
c. 記憶體池機制
Python提供了對記憶體的垃圾收集機制,但是它將不用的記憶體放到記憶體池而不是返回給作業系統。
1)Pymalloc機制。為了加速Python的執行效率,Python引入了一個記憶體池機制,用於管理對小塊記憶體的申請和釋放。
2)Python中所有小於256個位元組的物件都使用pymalloc實現的分配器,而大的物件則使用系統的 malloc。
3)對於Python物件,如整數,浮點數和List,都有其獨立的私有記憶體池,物件間不共享他們的記憶體池。也就是說如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。
【Python環境】12道 Python面試題總結
2、什麼是lambda函式?它有什麼好處?
lambda 表示式,通常是在需要一個函式,但是又不想費神去命名一個函式的場合下使用,也就是指匿名函式
lambda函式:首要用途是指點短小的回撥函式
lambda [arguments]: expression
>>> a=lambda x,y:x+y
>>> a(3,11)
3、Python裡面如何實現tuple和list的轉換?
直接使用tuple和list函式就行了,type()可以判斷物件的型別。
這個地方用set可以實現。
5、Python裡面如何複製一個物件?(賦值,淺複製,深複製的區別)
賦值(=),就是建立了物件的一個新的引用,修改其中任意一個變數都會影響到另一個。
淺複製:建立一個新的物件,但它包含的是對原始物件中包含項的引用(如果用引用的方式修改其中一個物件,另外一個也會修改改變){1,完全切片方法;2,工廠函式,如list();3,copy模組的copy()函式}
深複製:建立一個新的物件,並且遞迴的複製它所包含的物件(修改其中一個,另外一個不會改變){copy模組的deep.deepcopy()函式}
6、介紹一下except的用法和作用?
try…except…except…[else…][finally…]
執行try下的語句,如果引發異常,則執行過程會跳到except語句。對每個except分支順序嘗試執行,如果引發的異常與except中的異常組匹配,執行相應的語句。如果所有的except都不匹配,則異常會傳遞到下一個呼叫本程式碼的最高層try程式碼中。
try下的語句正常執行,則執行else塊程式碼。如果發生異常,就不會執行
如果存在finally語句,最後總是會執行。
7、Python裡面match()和search()的區別?
re模組中match(pattern,string [,flags]),檢查string的開頭是否與pattern匹配。
re模組中research(pattern,string [,flags]),在string搜尋pattern的第一個匹配值。
>>> print(re.match(‘super’, ‘superstition’).span())
(0, 5)
>>> print(re.match(‘super’, ‘insuperable’))
None
>>> print(re.search(‘super’, ‘superstition’).span())
>>> print(re.search(‘super’, ‘insuperable’).span())
(2, 7)
8、用Python匹配HTML tag的時候,<.*>和<.*?>有什麼區別?
術語叫貪婪匹配( <.*> )和非貪婪匹配( <.*?> )
例如:
test
<.*> :
<.*?> :
9、以下的程式碼的輸出將是什麼? 說出你的答案並解釋
輸出:
使你困惑或是驚奇的是關於最後一行的輸出是 3 2 3 而不是 3 2 1。為什麼改變了 Parent.x 的值還會改變 Child2.x 的值,但是同時 Child1.x 值卻沒有改變?
這
個答案的關鍵是,在 Python
中,類變數在內部是作為字典處理的。如果一個變數的名字沒有在當前類的字典中發現,將搜尋祖先類(比如父類)直到被引用的變數名被找到(如果這個被引用的
變數名既沒有在自己所在的類又沒有在祖先類中找到,會引發一個 AttributeError 異常 )。
因此,在父類中設定 x = 1 會使得類變數 X 在引用該類和其任何子類中的值為 1。這就是因為第一個 print 語句的輸出是 1 1 1。
隨後,如果任何它的子類重寫了該值(例如,我們執行語句 Child1.x = 2),然後,該值僅僅在子類中被改變。這就是為什麼第二個 print 語句的輸出是 1 2 1。
最後,如果該值在父類中被改變(例如,我們執行語句 Parent.x = 3),這個改變會影響到任何未重寫該值的子類當中的值(在這個示例中被影響的子類是 Child2)。這就是為什麼第三個 print 輸出是 3 2 3。
10、以下程式碼將輸出什麼?
答案
以上程式碼將輸出 [],並且不會導致一個 IndexError。
正如人們所期望的,試圖訪問一個超過列表索引值的成員將導致 IndexError(比如訪問以上列表的 list[10])。儘管如此,試圖訪問一個列表的以超出列表成員數作為開始索引的切片將不會導致 IndexError,並且將僅僅返回一個空列表。
一個討厭的小問題是它會導致出現 bug ,並且這個問題是難以追蹤的,因為它在執行時不會引發錯誤。
11、以下的程式碼的輸出將是什麼? 說出你的答案並解釋?
你將如何修改 extendList 的定義來產生期望的結果
以上程式碼的輸出為:
許多人會錯誤的認為 list1 應該等於 [10] 以及 list3 應該等於 ["a"]。認為 list 的引數會在 extendList 每次被呼叫的時候會被設定成它的預設值 []。
儘管如此,實際發生的事情是,新的預設列表僅僅只在函式被定義時建立一次。隨後當 extendList 沒有被指定的列表引數呼叫的時候,其使用的是同一個列表。這就是為什麼當函式被定義的時候,表示式是用預設引數被計算,而不是它被呼叫的時候。
因此,list1 和 list3 是操作的相同的列表。而 ````list2是操作的它建立的獨立的列表(透過傳遞它自己的空列表作為list``` 引數的值)。
extendList 函式的定義可以做如下修改,但,當沒有新的 list 引數被指定的時候,會總是開始一個新列表,這更加可能是一直期望的行為。
12、以下程式輸出什麼?
好
吧,第一行程式碼覺對是我第一次見,第一行輸出的是[[], [], [], [], []],一個含有5個空列表的列表,而第二行輸出的是[[10],
[10], [10], [10],
[10]],我只能解釋為這5個列表指向了同一個列表,所以修改任意一個其它4個都會改變,可以用list[0]=10 斷開一個連線試試。
1、Python是如何進行bai記憶體管理du的?
Python的記憶體管理主要有三種機制:引用計數zhi機制、垃圾回收dao機制和記憶體池機制。
a. 引用計數
當給一個物件分配一個新名稱或者將一個物件放入一個容器(列表、元組或字典)時,該物件的引用計數都會增加。
當使用del對物件顯示銷燬或者引用超出作用於或者被重新賦值時,該物件的引用計數就會減少。
可以使用sys.getrefcount()函式來獲取物件的當前引用計數。多數情況下,引用計數要比我們猜測的大的 多。對於不可變資料(數字和字串),直譯器會在程式的不同部分共享記憶體,以便節約記憶體。
b. 垃圾回收
當一個物件的引用計數歸零時,它將被垃圾收集機制處理掉。
當
兩個物件a和b相互引用時,del語句可以減少a和b的引用計數,並銷燬用於引用底層物件的名稱。然而由於每個物件都包含一個對其他物件的應用,因此引用
c. 記憶體池機制
Python提供了對記憶體的垃圾收集機制,但是它將不用的記憶體放到記憶體池而不是返回給作業系統。
1)Pymalloc機制。為了加速Python的執行效率,Python引入了一個記憶體池機制,用於管理對小塊記憶體的申請和釋放。
2)Python中所有小於256個位元組的物件都使用pymalloc實現的分配器,而大的物件則使用系統的 malloc。
3)對於Python物件,如整數,浮點數和List,都有其獨立的私有記憶體池,物件間不共享他們的記憶體池。也就是說如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。
【Python環境】12道 Python面試題總結
2、什麼是lambda函式?它有什麼好處?
lambda 表示式,通常是在需要一個函式,但是又不想費神去命名一個函式的場合下使用,也就是指匿名函式
lambda函式:首要用途是指點短小的回撥函式
lambda [arguments]: expression
>>> a=lambda x,y:x+y
>>> a(3,11)
3、Python裡面如何實現tuple和list的轉換?
直接使用tuple和list函式就行了,type()可以判斷物件的型別。
這個地方用set可以實現。
5、Python裡面如何複製一個物件?(賦值,淺複製,深複製的區別)
賦值(=),就是建立了物件的一個新的引用,修改其中任意一個變數都會影響到另一個。
淺複製:建立一個新的物件,但它包含的是對原始物件中包含項的引用(如果用引用的方式修改其中一個物件,另外一個也會修改改變){1,完全切片方法;2,工廠函式,如list();3,copy模組的copy()函式}
深複製:建立一個新的物件,並且遞迴的複製它所包含的物件(修改其中一個,另外一個不會改變){copy模組的deep.deepcopy()函式}
6、介紹一下except的用法和作用?
try…except…except…[else…][finally…]
執行try下的語句,如果引發異常,則執行過程會跳到except語句。對每個except分支順序嘗試執行,如果引發的異常與except中的異常組匹配,執行相應的語句。如果所有的except都不匹配,則異常會傳遞到下一個呼叫本程式碼的最高層try程式碼中。
try下的語句正常執行,則執行else塊程式碼。如果發生異常,就不會執行
如果存在finally語句,最後總是會執行。
【Python環境】12道 Python面試題總結
7、Python裡面match()和search()的區別?
re模組中match(pattern,string [,flags]),檢查string的開頭是否與pattern匹配。
re模組中research(pattern,string [,flags]),在string搜尋pattern的第一個匹配值。
>>> print(re.match(‘super’, ‘superstition’).span())
(0, 5)
>>> print(re.match(‘super’, ‘insuperable’))
None
>>> print(re.search(‘super’, ‘superstition’).span())
(0, 5)
>>> print(re.search(‘super’, ‘insuperable’).span())
(2, 7)
8、用Python匹配HTML tag的時候,<.*>和<.*?>有什麼區別?
術語叫貪婪匹配( <.*> )和非貪婪匹配( <.*?> )
例如:
test
<.*> :
test
<.*?> :
9、以下的程式碼的輸出將是什麼? 說出你的答案並解釋
輸出:
使你困惑或是驚奇的是關於最後一行的輸出是 3 2 3 而不是 3 2 1。為什麼改變了 Parent.x 的值還會改變 Child2.x 的值,但是同時 Child1.x 值卻沒有改變?
這
個答案的關鍵是,在 Python
中,類變數在內部是作為字典處理的。如果一個變數的名字沒有在當前類的字典中發現,將搜尋祖先類(比如父類)直到被引用的變數名被找到(如果這個被引用的
變數名既沒有在自己所在的類又沒有在祖先類中找到,會引發一個 AttributeError 異常 )。
因此,在父類中設定 x = 1 會使得類變數 X 在引用該類和其任何子類中的值為 1。這就是因為第一個 print 語句的輸出是 1 1 1。
隨後,如果任何它的子類重寫了該值(例如,我們執行語句 Child1.x = 2),然後,該值僅僅在子類中被改變。這就是為什麼第二個 print 語句的輸出是 1 2 1。
最後,如果該值在父類中被改變(例如,我們執行語句 Parent.x = 3),這個改變會影響到任何未重寫該值的子類當中的值(在這個示例中被影響的子類是 Child2)。這就是為什麼第三個 print 輸出是 3 2 3。
10、以下程式碼將輸出什麼?
答案
以上程式碼將輸出 [],並且不會導致一個 IndexError。
正如人們所期望的,試圖訪問一個超過列表索引值的成員將導致 IndexError(比如訪問以上列表的 list[10])。儘管如此,試圖訪問一個列表的以超出列表成員數作為開始索引的切片將不會導致 IndexError,並且將僅僅返回一個空列表。
【Python環境】12道 Python面試題總結
一個討厭的小問題是它會導致出現 bug ,並且這個問題是難以追蹤的,因為它在執行時不會引發錯誤。
11、以下的程式碼的輸出將是什麼? 說出你的答案並解釋?
你將如何修改 extendList 的定義來產生期望的結果
以上程式碼的輸出為:
許多人會錯誤的認為 list1 應該等於 [10] 以及 list3 應該等於 ["a"]。認為 list 的引數會在 extendList 每次被呼叫的時候會被設定成它的預設值 []。
儘管如此,實際發生的事情是,新的預設列表僅僅只在函式被定義時建立一次。隨後當 extendList 沒有被指定的列表引數呼叫的時候,其使用的是同一個列表。這就是為什麼當函式被定義的時候,表示式是用預設引數被計算,而不是它被呼叫的時候。
因此,list1 和 list3 是操作的相同的列表。而 ````list2是操作的它建立的獨立的列表(透過傳遞它自己的空列表作為list``` 引數的值)。
extendList 函式的定義可以做如下修改,但,當沒有新的 list 引數被指定的時候,會總是開始一個新列表,這更加可能是一直期望的行為。
12、以下程式輸出什麼?
好
吧,第一行程式碼覺對是我第一次見,第一行輸出的是[[], [], [], [], []],一個含有5個空列表的列表,而第二行輸出的是[[10],
[10], [10], [10],
[10]],我只能解釋為這5個列表指向了同一個列表,所以修改任意一個其它4個都會改變,可以用list[0]=10 斷開一個連線試試。