想找乙份python開發工作嗎?那你很可能得證明自己知道如何使用python。下面這些問題涉及了與python相關的許多技能,問題的關注點主要是語言本身,不是某個特定的包或模組。每乙個問題都可以擴充為乙個教程,如果可能的話。某些問題甚至會涉及多個領域。
我之前還沒有出過和這些題目一樣難的面試題,如果你能輕鬆地回答出來的話,趕緊去找份工作吧!
到底什麼是python?你可以在回答中與其他技術進行對比(也鼓勵這樣做)。答案
下面是一些關鍵點:
為什麼提這個問題:
如果你應聘的是乙個python開發崗位,你就應該知道這是門什麼樣的語言,以及它為什麼這麼酷。以及它**不好。
補充缺失的**
def print_directory_contents(spath):答案""" 這個函式接受資料夾的名稱作為輸入引數, 返回該資料夾中檔案的路徑, 以及其包含資料夾中檔案的路徑。 """ # 補充**
def print_directory_contents(spath):import os for schild in os.listdir(spath): schildpath = os.path.join(spath,schild) if os.path.isdir(schildpath): print_directory_contents(schildpath) else: print schildpath
特別要注意以下幾點:
為什麼提這個問題:
閱讀下面的**,寫出a0,a1至an的最終值。
a0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5))) a1 = range(10) a2 = [i for i in a1 if i in a0] a3 = [a0[s] for s in a0] a4 = [i for i in a1 if i in a3] a5 = a6 = [[i,i*i] for i in a1]答案
a0 = a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] a2 = a3 = [1, 3, 2, 5, 4] a4 = [1, 2, 3, 4, 5] a5 = a6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
為什麼提這個問題:
python和多執行緒(multi-threading)。這是個好主意碼?列舉一些讓python**以並行方式執行的方法。答案
python並不支援真正意義上的多執行緒。python中提供了多執行緒包,但是如果你想通過多執行緒提高**的速度,使用多執行緒包並不是個好主意。python中有乙個被稱為global interpreter lock(gil)的東西,它會確保任何時候你的多個執行緒中,只有乙個被執行。執行緒的執行速度非常之快,會讓你誤以為執行緒是並行執行的,但是實際上都是輪流執行。經過gil這一道關卡處理,會增加執行的開銷。這意味著,如果你想提高**的執行速度,使用threading
包並不是乙個很好的方法。
不過還是有很多理由促使我們使用threading
包的。如果你想同時執行一些任務,而且不考慮效率問題,那麼使用這個包是完全沒問題的,而且也很方便。但是大部分情況下,並不是這麼一回事,你會希望把多執行緒的部分外包給作業系統完成(通過開啟多個程序),或者是某些呼叫你的python**的外部程式(例如spark或hadoop),又或者是你的python**呼叫的其他**(例如,你可以在python中呼叫c函式,用於處理開銷較大的多執行緒工作)。
為什麼提這個問題
因為gil就是個混賬東西(a-hole)。很多人花費大量的時間,試圖尋找自己多執行緒**中的瓶頸,直到他們明白gil的存在。
你如何管理不同版本的**?
答案:版本管理!被問到這個問題的時候,你應該要表現得很興奮,甚至告訴他們你是如何使用git(或是其他你最喜歡的工具)追蹤自己和奶奶的書信往來。我偏向於使用git作為版本控制系統(vcs),但還有其他的選擇,比如subversion(svn)。
為什麼提這個問題:
因為沒有版本控制的**,就像沒有杯子的咖啡。有時候我們需要寫一些一次性的、可以隨手扔掉的指令碼,這種情況下不作版本控制沒關係。但是如果你面對的是大量的**,使用版本控制系統是有利的。版本控制能夠幫你追蹤誰對**庫做了什麼操作;發現新引入了什麼bug;管理你的軟體的不同版本和發行版;在團隊成員中分享源**;部署及其他自動化處理。它能讓你回滾到出現問題之前的版本,單憑這點就特別棒了。還有其他的好功能。怎麼乙個棒字了得!
下面**會輸出什麼:
答案:
[0, 1][3, 2, 1, 0, 1, 4] [0, 1, 0, 1, 4]
呃?第乙個函式呼叫十分明顯,for迴圈先後將0和1新增至了空列表l
中。l
是變數的名字,指向記憶體中儲存的乙個列表。第二個函式呼叫在一塊新的記憶體中建立了新的列表。l
這時指向了新生成的列表。之後再往新列表中新增0、1、2和4。很棒吧。第三個函式呼叫的結果就有些奇怪了。它使用了之前記憶體位址中儲存的舊列表。這就是為什麼它的前兩個元素是0和1了。
不明白的話就試著執行下面的**吧:
l_mem =
「猴子補丁」(monkey patching)指的是什麼?這種做法好嗎?
答案:「猴子補丁」就是指,在函式或物件已經定義之後,再去改變它們的行為。
舉個例子:
import datetimedatetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)
大部分情況下,這是種很不好的做法 - 因為函式在**庫中的行為最好是都保持一致。打「猴子補丁」的原因可能是為了測試。mock
包對實現這個目的很有幫助。
為什麼提這個問題?
答對這個問題說明你對單元測試的方法有一定了解。你如果提到要避免「猴子補丁」,可以說明你不是那種喜歡花裡胡哨**的程式設計師(公司裡就有這種人,跟他們共事真是糟糕透了),而是更注重可維護性。還記得kiss原則碼?答對這個問題還說明你明白一些python底層運作的方式,函式實際是如何儲存、呼叫等等。
另外:如果你沒讀過mock
模組的話,真的值得花時間讀一讀。這個模組非常有用。
這兩個引數是什麼意思:*args
,**kwargs
?我們為什麼要使用它們?答案
下面是具體的示例:
def f(*args,**kwargs): print args, kwargs l = [1,2,3] t = (4,5,6) d = f() f(1,2,3) # (1, 2, 3) {} f(1,2,3,"groovy") # (1, 2, 3, 'groovy') {} f(a=1,b=2,c=3) # () f(a=1,b=2,c=3,zzz="hi") # () f(1,2,3,a=1,b=2,c=3) # (1, 2, 3) f(*l,**d) # (1, 2, 3) f(*t,**d) # (4, 5, 6) f(1,2,*t) # (1, 2, 4, 5, 6) {} f(q="winning",**d) # () f(1,2,*t,q="winning",**d) # (1, 2, 4, 5, 6) def f2(arg1,arg2,*args,**kwargs): print arg1,arg2, args, kwargs f2(1,2,3) # 1 2 (3,) {} f2(1,2,3,"groovy") # 1 2 (3, 'groovy') {} f2(arg1=1,arg2=2,c=3) # 1 2 () f2(arg1=1,arg2=2,
你必須要看的IT培訓機構選擇意見
it是個一直很火熱的行業,大資料培訓也開始受到越來越多的關注,不少朋友都在糾結到底應該選擇哪一家培訓公司,選擇哪乙個行業,看看這裡有沒有你想要的解答。android培訓 黑馬程式設計師,據說進入黑馬培訓,需要經過2個多月的乙個測試,可謂門檻最高的android培訓公司,在android培訓培訓這一塊...
面試必須要懂的函式
define stl ifdef stl include include using namespace std char strcpy char dest,const char src char strncpy char dest,const char src,int count int strc...
面試前必須要知道的Redis面試題
回顧前面 從零單排學redis 青銅 從零單排學redis 從零單排學redis 從零單排學redis 鉑金一 從零單排學redis 鉑金二 redis 今天來分享一下redis幾道常見的面試題 如何解決快取雪崩?如何解決快取穿透?如何保證快取與資料庫雙寫時一致的問題?一 快取雪崩 1.1什麼是快取...