當前位置:
首頁 > 最新 > python簡單面試題

python簡單面試題

python簡單面試題

"真的猛士敢於冒著掛科的風險做自己喜歡的事"

——魯迅

1.Python是如何進行內存管理的?

答:從三個方面來說,一對象的引用計數機制,二垃圾回收機制,三內存池機制

一、對象的引用計數機制

Python內部使用引用計數,來保持追蹤內存中的對象,所有對象都有引用計數。

引用計數增加的情況:

1,一個對象分配一個新名稱

2,將其放入一個容器中(如列表、元組或字典)

引用計數減少的情況:

1,使用del語句對對象別名顯示的銷毀

2,引用超出作用域或被重新賦值

sys.getrefcount( )函數可以獲得對象的當前引用計數

多數情況下,引用計數比你猜測得要大得多。對於不可變數據(如數字和字元串),解釋器會在程序的不同部分共享內存,以便節約內存。

二、垃圾回收

1,當一個對象的引用計數歸零時,它將被垃圾收集機制處理掉。

2,當兩個對象a和b相互引用時,del語句可以減少a和b的引用計數,並銷毀用於引用底層對象的名稱。然而由於每個對象都包含一個對其他對象的應用,因此引用計數不會歸零,對象也不會銷毀。(從而導致內存泄露)。為解決這一問題,解釋器會定期執行一個循環檢測器,搜索不可訪問對象的循環並刪除它們。

三、內存池機制

Python提供了對內存的垃圾收集機制,但是它將不用的內存放到內存池而不是返回給操作系統。

1,Pymalloc機制。為了加速Python的執行效率,Python引入了一個內存池機制,用於管理對小塊內存的申請和釋放。

2,Python中所有小於256個位元組的對象都使用pymalloc實現的分配器,而大的對象則使用系統的malloc。

3,對於Python對象,如整數,浮點數和List,都有其獨立的私有內存池,對象間不共享他們的內存池。也就是說如果你分配又釋放了大量的整數,用於緩存這些整數的內存就不能再分配給浮點數。

2.什麼是lambda函數?它有什麼好處?

答:lambda 表達式,通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數

lambda函數:首要用途是指點短小的回調函數

3.Python裡面如何實現tuple和list的轉換?

答:直接使用tuple和list函數就行了,type()可以判斷對象的類型

4.請寫出一段Python代碼實現刪除一個list裡面的重複元素

答:

1,使用set函數,set(list)

2,使用字典函數,

5.編程用sort進行排序,然後從最後一個元素開始判斷

6.Python裡面如何拷貝一個對象?(賦值,淺拷貝,深拷貝的區別)

答:賦值(=),就是創建了對象的一個新的引用,修改其中任意一個變數都會影響到另一個。

淺拷貝:創建一個新的對象,但它包含的是對原始對象中包含項的引用(如果用引用的方式修改其中一個對象,另外一個也會修改改變)

深拷貝:創建一個新的對象,並且遞歸的複製它所包含的對象(修改其中一個,另外一個不會改變)

7.介紹一下except的用法和作用?

答:try…except…except…[else…][finally…]

執行try下的語句,如果引發異常,則執行過程會跳到except語句。對每個except分支順序嘗試執行,如果引發的異常與except中的異常組匹配,執行相應的語句。如果所有的except都不匹配,則異常會傳遞到下一個調用本代碼的最高層try代碼中。

try下的語句正常執行,則執行else塊代碼。如果發生異常,就不會執行

如果存在finally語句,最後總是會執行。

8.Python中pass語句的作用是什麼?

答:pass語句不會執行任何操作,一般作為佔位符或者創建佔位程序,whileFalse:pass

9.介紹一下Python下range()函數的用法?

答:列出一組數據,經常用在for in range()循環中

10.如何用Python來進行查詢和替換一個文本字元串?

答:可以使用re模塊中的sub()函數或者subn()函數來進行查詢和替換,

格式:sub(replacement, string[,count=0])(replacement是被替換成的文本,string是需要被替換的文本,count是一個可選參數,指最大被替換的數量)

subn()方法執行的效果跟sub()一樣,不過它會返回一個二維數組,包括替換後的新的字元串和總共替換的數量

11.Python裡面match()和search()的區別?

答:re模塊中match(pattern,string[,flags]),檢查string的開頭是否與pattern匹配。

re模塊中research(pattern,string[,flags]),在string搜索pattern的第一個匹配值。

12.用Python匹配HTML tag的時候,>和?>有什麼區別?

答:術語叫貪婪匹配( > )和非貪婪匹配(?> )

例如:

13.Python裡面如何生成隨機數?

答:random模塊

隨機整數:random.randint(a,b):返回隨機整數x,a

random.randrange(start,stop,[,step]):返回一個範圍在(start,stop,step)之間的隨機整數,不包括結束值。

隨機實數:random.random( ):返回0到1之間的浮點數

random.uniform(a,b):返回指定範圍內的浮點數。

14.有沒有一個工具可以幫助查找python的bug和進行靜態的代碼分析?

答:PyChecker是一個python代碼的靜態分析工具,它可以幫助查找python代碼的bug, 會對代碼的複雜度和格式提出警告

Pylint是另外一個工具可以進行codingstandard檢查

15.如何在一個function裡面設置一個全局的變數?

答:解決方法是在function的開始插入一個global聲明:

16.單引號,雙引號,三引號的區別

答:單引號和雙引號是等效的,如果要換行,需要符號(),三引號則可以直接換行,並且可以包含注釋

如果要表示Let』s go 這個字元串

這就是單引號和雙引號都可以表示字元串的原因了

休息一下

下面的代碼輸出什麼?

上面的代碼輸出[],並且不會導致IndexError錯誤

跟你想的一樣,當取列表元素的時候,如果索引值超過了元素的個數(例如在上面的列表中,取list[10])將會導致IndexError錯誤。但是,取一個列表的切片的時候,如果起始索引超過了元素個數,將不會引起IndexError錯誤,僅返回一個空列表。

這一特性將會導致一些非常難於追蹤的bug,因為在運行時根本沒有錯誤產生。

下面的代碼在Python2中的輸出是什麼?解釋你的答案

另外,在Python3中上面的代碼的輸出有何不同(假設代碼中的print語句都轉化成了Python3中的語法結構)?

在Python2中,代碼的輸出是:

默認情況下,如果兩個操作數都是整數,Python2默認執行整數運算。所以,5/2 結果是2,而5./2結果是2.5

注意你可以通過下面的import語句來覆蓋Python2中的這一行為

fromfutureimport division

還要注意「雙斜杠」(//)操作符將會一直執行整除,忽略操作數的類型。這就是為什麼5.0//2.0即使在Python2中結果也是2.0

但是在Python3並沒有這一行為。兩個操作數都是整數時,也不執行整數運算。在Python3中,輸出如下:

下面代碼的輸出是什麼?請解釋你的答案

如何修改函數ExtendList的定義才能產生我們希望的行為?

輸出為:

很多人會錯誤地預計list1等於[10],list3等於["a"],認為extendList函數的list參數在每一次函數被調用時都會被設置為默認值[]

但是,真實的情況是,默認的list只在函數定義的時候被創建一次。之後不指定list參數地調用extendList函數時,使用的都是同一個list。這是因為帶默認參數的表達式是在函數定義的時候被計算的,而不是在函數調用時。

所以,list1和list3都是在操作同一個默認list,而list2是在操作它自己創建的一個獨立的list(將自己的空list作為參數傳遞過去)

extendlist的定義可以這樣定義來達到我們預期的效果:

調用修改後的函數,輸出是:

下面代碼的輸出是什麼?請解釋你的答案

讓很多人感到疑惑和驚訝的是,最後一行的輸出竟然不是3 2 1而是3 2 3. 為什麼修改了Parent.X的值會影響到Child2.x,但是同時又沒有改變Child1.x的值呢?

這個問題的關鍵在於,在python中,類中的變數在內部被當作字典處理。如果一個變數名在當前類的字典中沒有被發現,系統將會在這個類的祖先(例如,它的父類)中繼續尋找,直到找到為止(如果一個變數名在這個類和這個類的祖先中都沒有,那麼將會引發一個AttributeError錯誤)

因此,在父類中將變數x賦值為1,那麼x變數將可以被當前類和所有這個類的子類引用。這就是為什麼第一個print語句輸出為1 1 1.

接下來,如果它的子類覆蓋了這個值(例如, 當我們執行Child1.x = 2),那麼這個變數的值僅僅在這個子類中發生了改變。這就是為什麼第二個print語句輸出1 2 1

最後,如果父類改變了這個變數的值(例如,我們執行Parent.x = 3),所有沒有覆蓋這個參數值的子類(在這個例子中覆蓋了參數的就是Child2)都會受到影響,這就是為什麼第三個print語句的輸出為3 2 3

下面代碼的輸出是什麼?請解釋你的答案

怎麼修改multipliers的定義才能達到期望的效果?

上面代碼的輸出是[6, 6, 6, 6](不是[0, 2, 4, 6]).

原因是Python的閉包是延遲綁定(late binding)的。這表明在閉包中使用的變數直到內層函數被調用的時候才會被查找。結果是,當調用multipliers()返回的函數時,i參數的值會在這時被在調用環境中查找。所以,無論調用返回的哪個函數,for循環此時已經結束,i等於它最終的值3。因此,所有返回的函數都要乘以傳遞過來的3,因為上面的代碼傳遞了2作為參數,所以他們都返回了6(即,3 * 2)

(順便提一句,正如在書《The Hitchhiker』s Guide to Python》中提出來的一樣, 有一種廣泛傳播的誤解認為這個問題和lambda表達式有關,事實並非如此。通過labda表達式產生的函數並沒有什麼特別之處,使用普通的def定義的函數的行為和lambda表達式產生的函數的行為是一樣的.)

下面是一些可以繞過這個問題的方法。

方法一是像下面一樣使用Python的生成器(generator)

另一個方法是創造一個閉包,通過使用一個默認參數來立即綁定它的參數

或者,你也可以使用functools.partial函數:

考慮下面的代碼片段:

第2,4,6,8行的輸出是什麼?解釋你的答案.

輸出如下:

下面是解釋:

第一行的輸出憑直覺就能知道,很容易理解。即:list = [ [ ] ] * 5創建了一個元素是5個列表的列表。

但是,這裡要理解的關鍵是,list = [ [ ] ] * 5並沒有創建一個包含5個不同列表的列表。創建的這個列表裡的5個列表,是對同一個列表的引用(a a list of 5 references to the same list)。理解了這些,你就能更好地理解餘下的輸出。

list[0].append(10)將數字10添加到第一個列表。但是由於5個列表是對同一個列表的引用,所以輸出是[[10], [10], [10], [10], [10]]。

同樣的,list[1].append(20)將20追加到第二個列表。但是同樣,由於這5個列表引用同一個列表,所以輸出:[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]].

相比之下, list.append(30)是將一個全新的元素追加到「外層」的列表,所以產生了這樣的輸出:[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30].

有一個擁有N個元素的列表,用一個列表解析式生成一個新的列表,元素的值同時滿足以下條件:

(a) 偶數,以及

(b) 在原列表中,索引為偶數

例如,如果list[2]的值是偶數,那麼這個元素應該也被包含在新列表中,因為它在原列表中的索引也是偶數(即 2). 但是, 如果list[3]是偶數,那這個值不應該被包含在新列表中,因為它在原列表中的索引是一個奇數。

一個簡單的解法如下:

例如,給出下面的列表:

list = [ 1 , 3 , 5 , 8 , 10 , 13 , 18 , 36 , 78 ]

列表解析式[x for x in list[::2] if x%2 == 0] 會生成:

這個表達式首先取列表中索引是偶數的數字,然後過濾掉所有的奇數。

點關注不迷路


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 阿信在努力 的精彩文章:

python模塊與包揭秘

TAG:阿信在努力 |