當前位置:
首頁 > 知識 > 5 個很好的 Python 面試題

5 個很好的 Python 面試題

問題一:以下的代碼的輸出將是什麼? 說出你的答案並解釋。






class

Parent

(

object

)

:


x

=

1



class

Child1

(

Parent

)

:


pass


class

Child2

(

Parent

)

:


pass



print

Parent

.

x

,

Child1

.

x

,

Child2

.

x


Child1

.

x

=

2


print

Parent

.

x

,

Child1

.

x

,

Child2

.

x


Parent

.

x

=

3


print

Parent

.

x

,

Child1

.

x

,

Child2

.

x




答案




以上代碼的輸出是:





1

1

1


1

2

1


3

2

3




使你困惑或是驚奇的是關於最後一行的輸出是 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。




問題二:以下的代碼的輸出將是什麼? 說出你的答案並解釋?





def div1

(

x

,

y

)

:


print

(

"%s/%s = %s"

%

(

x

,

y

,

x

/

y

))



def div2

(

x

,

y

)

:


print

(

"%s//%s = %s"

%

(

x

,

y

,

x

//y))



div1

(

5

,

2

)


div1

(

5.

,

2

)


div2

(

5

,

2

)


div2

(

5.

,

2.

)




答案




這個答案實際依賴於你使用的是 Python 2 還是 Python 3。




在 Python 3 中,期望的輸出是:





5

/

2

=

2.5


5.0

/

2

=

2.5


5

//2 = 2


5.0

//2.0 = 2.0




在 Python 2 中,儘管如此,以上代碼的輸出將是:





5

/

2

=

2


5.0

/

2

=

2.5


5

//2 = 2


5.0

//2.0 = 2.0




默認,如果兩個操作數都是整數,Python 2 自動執行整型計算。結果,5/2 值為 2,然而 5./2 值為 2.5。




注意,儘管如此,你可以在 Python 2 中重載這一行為(比如達到你想在 Python 3 中的同樣結果),通過添加以下導入:





from __future__ import

division




也需要注意的是「雙劃線」(//)操作符將一直執行整除,而不管操作數的類型,這就是為什麼 5.0//2.0 值為 2.0。





註: 在 Python 3 中,/ 操作符是做浮點除法,而 // 是做整除(即商沒有餘數,比如 10 // 3 其結果就為 3,餘數會被截除掉,而 (-7) // 3 的結果卻是 -3。這個演算法與其它很多編程語言不一樣,需要注意,它們的整除運算會向0的方向取值。而在 Python 2 中,/ 就是整除,即和 Python 3 中的 // 操作符一樣,)




問題三:以下代碼將輸出什麼?





list

=

[

"a"

,

"b"

,

"c"

,

"d"

,

"e"

]


print

list

[

10

:

]




答案




以上代碼將輸出 [],並且不會導致一個 IndexError。




正如人們所期望的,試圖訪問一個超過列表索引值的成員將導致 IndexError(比如訪問以上列表的 list[10])。儘管如此,試圖訪問一個列表的以超出列表成員數作為開始索引的切片將不會導致 IndexError,並且將僅僅返回一個空列表。




一個討厭的小問題是它會導致出現 bug ,並且這個問題是難以追蹤的,因為它在運行時不會引發錯誤。




問題四:以下的代碼的輸出將是什麼? 說出你的答案並解釋?





def multipliers

()

:


return

[

lambda

x

:

i *

x

for

i

in

range

(

4

)]



print

[

m

(

2

)

for

m

in

multipliers

()]




你將如何修改 multipliers 的定義來產生期望的結果




答案




以上代碼的輸出是 [6, 6, 6, 6] (而不是 [0, 2, 4, 6])。




這個的原因是 Python 的閉包的後期綁定導致的 late binding,這意味著在閉包中的變數是在內部函數被調用的時候被查找。所以結果是,當任何 multipliers() 返回的函數被調用,在那時,i 的值是在

它被調用時的周圍作用域中查找

,到那時,無論哪個返回的函數被調用,for 循環都已經完成了,i 最後的值是 3,因此,每個返回的函數 multiplies 的值都是 3。因此一個等於 2 的值被傳遞進以上代碼,它們將返回一個值 6 (比如: 3 x 2)。




(順便說下,正如在 The Hitchhiker』s Guide to Python 中指出的,這裡有一點普遍的誤解,是關於 lambda 表達式的一些東西。一個 lambda 表達式創建的函數不是特殊的,和使用一個普通的 def 創建的函數展示的表現是一樣的。)




這裡有兩種方法解決這個問題。




最普遍的解決方案是創建一個閉包,通過使用默認參數立即綁定它的參數。例如:





def multipliers

()

:


return

[

lambda

x

,

i

=

i

:

i *

x

for

i

in

range

(

4

)]




另外一個選擇是,你可以使用 functools.partial 函數:





from functools import partial


from operator import mul



def multipliers

()

:


return

[

partial

(

mul

,

i

)

for

i

in

range

(

4

)]




問題五:以下的代碼的輸出將是什麼? 說出你的答案並解釋?





def extendList

(

val

,

list

=

[])

:


list

.

append

(

val

)


return

list



list1

=

extendList

(

10

)


list2

=

extendList

(

123

,[])


list3

=

extendList

(

"a"

)



print

"list1 = %s"

%

list1


print

"list2 = %s"

%

list2


print

"list3 = %s"

%

list3




你將如何修改 extendList 的定義來產生期望的結果




以上代碼的輸出為:





list1

=

[

10

,

"a"

]


list2

=

[

123

]


list3

=

[

10

,

"a"

]




許多人會錯誤的認為 list1 應該等於 [10] 以及 list3 應該等於 ["a"]。認為 list 的參數會在 extendList 每次被調用的時候會被設置成它的默認值 []。




儘管如此,實際發生的事情是,新的默認列表僅僅只在函數被定義時創建一次。隨後當 extendList 沒有被指定的列表參數調用的時候,其使用的是同一個列表。這就是為什麼當函數被定義的時候,表達式是用默認參數被計算,而不是它被調用的時候。




因此,list1 和 list3 是操作的相同的列表。而 list2是操作的它創建的獨立的列表(通過傳遞它自己的空列表作為list 參數的值)。




extendList 函數的定義可以做如下修改

,但,當沒有新的 list 參數被指定的時候,會總是開始一個新列表,這更加可能是一直期望的行為。





def extendList

(

val

,

list

=

None

)

:


if

list

is

None

:


list

=

[]


list

.

append

(

val

)


return

list




使用這個改進的實現,輸出將是:





list1

=

[

10

]


list2

=

[

123

]


list3

=

[

"a"

]





註:本文的原文是 5 Great Python Interview Questions,同時謝謝 @非烏龜 指出我的疏漏,沒有來源標記,也贊其細心,希望看文章的同時大家都能看下原文,因為每個人的理解不一致,原汁原味的最有幫助,我翻譯很多文章的目的一是為了自己以後找資料方便;二是作為一個索引,以後再看原文的時候,能更加快捷。其目的還是希望大家能看原文的。






  • 英文:toptal



  • 譯文:yexiaobai



  • 鏈接:segmentfault.com/a/1190000000618513



  • 程序員大咖整理髮布,轉載請聯繫作者獲得授權


↙點擊「

閱讀原文

」,加入


『程序員大咖』

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

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


請您繼續閱讀更多來自 Python 的精彩文章:

數據專家必知必會的7款Python工具
Python超級程序員使用的開發工具
基於 Agent 的模型入門:Python 實現隔離模擬
編程語言中的超級英雄們:Python如同蝙蝠戰車,Ruby可比蝙蝠俠……

TAG:Python |

您可能感興趣

Python面試必須要看的15個問題
10個Python面試問題,檢驗你python真實水平
最常見的 35個Python 面試題及答案
10個Python常見面試題,這些弄不明白不要說學過Python!
Python 面試中 8 個必考問題
搞定這套 Python 爬蟲面試題,面試會 so easy
這4個Python實戰項目,讓你瞬間讀懂Python!
寫 Python 時的 5 個壞習慣 | python3
Python經典面試題21道
Python 經典面試題 21 道
python簡單面試題
Python指南:Python的8個關鍵要素
13個Python Web框架比較,你想使用哪個呢?
百道Python面試題實現,搞定Python編程就靠它
在 GitHub 上收穫 6519顆Star 的 Python 面試題資源,到底有多牛?
Effective Python之編寫高質量Python代碼的59個有效方法
Python面試攻略
Python 的 except 怪癖
python下的測試利器pytest
Python面試攻略(coding篇)