1. 程式人生 > >Python面試必須要了解的15個問題

Python面試必須要了解的15個問題


訪問flyai.club,一鍵建立你的人工智慧專案



譯文 | [email protected]程式設計派

原文 | [email protected] 


引言


想找一份Python開發工作嗎?那你很可能得證明自己知道如何使用Python。下面這些問題涉及了與Python相關的許多技能,問題的關注點主要是語言本身,不是某個特定的包或模組。每一個問題都可以擴充為一個教程,如果可能的話。某些問題甚至會涉及多個領域。


我之前還沒有出過和這些題目一樣難的面試題,如果你能輕鬆地回答出來的話,趕緊去找份工作吧!


問題1


到底什麼是Python?你可以在回答中與其他技術進行對比(也鼓勵這樣做)。


答案


下面是一些關鍵點:


  • Python是一種解釋型語言。這就是說,與C語言和C的衍生語言不同,Python程式碼在執行之前不需要編譯。其他解釋型語言還包括PHP和Ruby。

  • Python是動態型別語言,指的是你在宣告變數時,不需要說明變數的型別。你可以直接編寫類似x=111和x="I'm a string"這樣的程式碼,程式不會報錯。

  • Python非常適合面向物件的程式設計(OOP),因為它支援通過組合(composition)與繼承(inheritance)的方式定義類(class)。Python中沒有訪問說明符(access specifier,類似C++中的public和private),這麼設計的依據是“大家都是成年人了”。

  • 在Python語言中,函式是第一類物件(first-class objects)。這指的是它們可以被指定給變數,函式既能返回函式型別,也可以接受函式作為輸入。類(class)也是第一類物件。

  • Python程式碼編寫快,但是執行速度比編譯語言通常要慢。好在Python允許加入基於C語言編寫的擴充套件,因此我們能夠優化程式碼,消除瓶頸,這點通常是可以實現的。numpy就是一個很好地例子,它的執行速度真的非常快,因為很多算術運算其實並不是通過Python實現的。

  • Python用途非常廣泛——網路應用,自動化,科學建模,大資料應用,等等。它也常被用作“膠水語言”,幫助其他語言和元件改善執行狀況。

  • Python讓困難的事情變得容易,因此程式設計師可以專注於演算法和資料結構的設計,而不用處理底層的細節。


為什麼提這個問題:


如果你應聘的是一個Python開發崗位,你就應該知道這是門什麼樣的語言,以及它為什麼這麼酷。以及它哪裡不好。


問題2


補充缺失的程式碼


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


特別要注意以下幾點:


  • 命名規範要統一。如果樣本程式碼中能夠看出命名規範,遵循其已有的規範。

  • 遞迴函式需要遞歸併終止。確保你明白其中的原理,否則你將面臨無休無止的呼叫棧(callstack)。

  • 我們使用os模組與作業系統進行互動,同時做到互動方式是可以跨平臺的。你可以把程式碼寫成sChildPath = sPath + '/' + sChild,但是這個在Windows系統上會出錯。

  • 熟悉基礎模組是非常有價值的,但是別想破腦袋都背下來,記住Google是你工作中的良師益友。

  • 如果你不明白程式碼的預期功能,就大膽提問。

  • 堅持KISS原則!保持簡單,不過腦子就能懂!


為什麼提這個問題:


  • 說明面試者對與作業系統互動的基礎知識

  • 遞迴真是太好用啦


問題3


閱讀下面的程式碼,寫出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 = {i:i*i for i in A1}A6 = [[i,i*i] for i in A1]


答案


A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}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 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]


為什麼提這個問題:


  • 列表解析(list comprehension)十分節約時間,對很多人來說也是一個大的學習障礙。

  • 如果你讀懂了這些程式碼,就很可能可以寫下正確地值。

  • 其中部分程式碼故意寫的怪怪的。因為你共事的人之中也會有怪人。


問題4


Python和多執行緒(multi-threading)。這是個好主意碼?列舉一些讓Python程式碼以並行方式執行的方法。


答案


Python並不支援真正意義上的多執行緒。Python中提供了多執行緒包,但是如果你想通過多執行緒提高程式碼的速度,使用多執行緒包並不是個好主意。Python中有一個被稱為Global Interpreter Lock(GIL)的東西,它會確保任何時候你的多個執行緒中,只有一個被執行。執行緒的執行速度非常之快,會讓你誤以為執行緒是並行執行的,但是實際上都是輪流執行。經過GIL這一道關卡處理,會增加執行的開銷。這意味著,如果你想提高程式碼的執行速度,使用threading包並不是一個很好的方法。


不過還是有很多理由促使我們使用threading包的。如果你想同時執行一些任務,而且不考慮效率問題,那麼使用這個包是完全沒問題的,而且也很方便。但是大部分情況下,並不是這麼一回事,你會希望把多執行緒的部分外包給作業系統完成(通過開啟多個程序),或者是某些呼叫你的Python程式碼的外部程式(例如Spark或Hadoop),又或者是你的Python程式碼呼叫的其他程式碼(例如,你可以在Python中呼叫C函式,用於處理開銷較大的多執行緒工作)。


為什麼提這個問題


因為GIL就是個混賬東西(A-hole)。很多人花費大量的時間,試圖尋找自己多執行緒程式碼中的瓶頸,直到他們明白GIL的存在。


問題5


你如何管理不同版本的程式碼?


答案:


版本管理!被問到這個問題的時候,你應該要表現得很興奮,甚至告訴他們你是如何使用Git(或是其他你最喜歡的工具)追蹤自己和奶奶的書信往來。我偏向於使用Git作為版本控制系統(VCS),但還有其他的選擇,比如subversion(SVN)。


為什麼提這個問題:


因為沒有版本控制的程式碼,就像沒有杯子的咖啡。有時候我們需要寫一些一次性的、可以隨手扔掉的指令碼,這種情況下不作版本控制沒關係。但是如果你面對的是大量的程式碼,使用版本控制系統是有利的。版本控制能夠幫你追蹤誰對程式碼庫做了什麼操作;發現新引入了什麼bug;管理你的軟體的不同版本和發行版;在團隊成員中分享原始碼;部署及其他自動化處理。它能讓你回滾到出現問題之前的版本,單憑這點就特別棒了。還有其他的好功能。怎麼一個棒字了得!


問題6


下面程式碼會輸出什麼:


def f(x,l=[]):
    for i in range(x):
        l.append(i*i)
    print lf(2)f(3,[3,2,1])f(3)


答案:


[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 = []l = l_mem           # the first callfor i in range(2):
    l.append(i*i)print l             # [0, 1]l = [3,2,1]         # the second callfor i in range(3):
    l.append(i*i)print l             # [3, 2, 1, 0, 1, 4]l = l_mem           # the third callfor i in range(3):
    l.append(i*i)print l             # [0, 1, 0, 1, 4]


問題7


“猴子補丁”(monkey patching)指的是什麼?這種做法好嗎?


答案:


“猴子補丁”就是指,在函式或物件已經定義之後,再去改變它們的行為。


舉個例子:


import datetimedatetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)


大部分情況下,這是種很不好的做法 - 因為函式在程式碼庫中的行為最好是都保持一致。打“猴子補丁”的原因可能是為了測試。mock包對實現這個目的很有幫助。

為什麼提這個問題?


答對這個問題說明你對單元測試的方法有一定了解。你如果提到要避免“猴子補丁”,可以說明你不是那種喜歡花裡胡哨程式碼的程式設計師(公司裡就有這種人,跟他們共事真是糟糕透了),而是更注重可維護性。還記得KISS原則碼?答對這個問題還說明你明白一些Python底層運作的方式,函式實際是如何儲存、呼叫等等。


另外:如果你沒讀過mock模組的話,真的值得花時間讀一讀。這個模組非常有用。


問題8


這兩個引數是什麼意思:*args,**kwargs?我們為什麼要使用它們?


答案


如果我們不確定要往函式中傳入多少個引數,或者我們想往函式中以列表和元組的形式傳引數時,那就使要用*args;如果我們不知道要往函式中傳入多少個關鍵詞引數,或者想傳入字典的值作為關鍵詞引數時,那就要使用**kwargs。args和kwargs這兩個識別符號是約定俗成的用法,你當然還可以用*bob和**billy,但是這樣就並不太妥。


下面是具體的示例:


def f(*args,**kwargs): print args, kwargsl = [1,2,3]t = (4,5,6)d = {'a':7,'b':8,'c':9}f()f(1,2,3)                    # (1, 2, 3) {}f(1,2,3,"groovy")           # (1, 2, 3, 'groovy') {}f(a=1,b=2,c=3)              # () {'a': 1, 'c': 3, 'b': 2}f(a=1,b=2,c=3,zzz="hi")     # () {'a': 1, 'c': 3, 'b': 2, 'zzz': 'hi'}f(1,2,3,a=1,b=2,c=3)        # (1, 2, 3) {'a': 1, 'c': 3, 'b': 2}f(*l,**d)                   # (1, 2, 3) {'a': 7, 'c': 9, 'b': 8}f(*t,**d)                   # (4, 5, 6) {'a': 7, 'c': 9, 'b': 8}f(1,2,*t)                   # (1, 2, 4, 5, 6) {}f(q="winning",**d)          # () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}f(1,2,*t,q="winning",**d)   # (1, 2, 4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}def f2(arg1,arg2,*args,**kwargs): print arg1,arg2, args, kwargsf2(1,2,3)                       # 1 2 (3,) {}f2(1,2,3,"groovy")              # 1 2 (3, 'groovy') {}f2(arg1=1,arg2=2,c=3)           # 1 2 () {'c': 3}f2(arg1=1,arg2=2,c=3,zzz="hi")  # 1 2 () {'c': 3, 'zzz': 'hi'}f2(1,2,3,a=1,b=2,c=3)           # 1 2 (3,) {'a': 1, 'c': 3, 'b': 2}f2(*l,**d)                   # 1 2 (3,) {'a': 7, 'c': 9, 'b': 8}f2(*t,**d)                   # 4 5 (6,) {'a': 7, 'c': 9, 'b': 8}f2(1,2,*t)                   # 1 2 (4, 5, 6) {}f2(1,1,q="winning",**d)      # 1 1 () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}f2(1,2,*t,q="winning",**d)   # 1 2 (4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}


為什麼提這個問題?


有時候,我們需要往函式中傳入未知個數的引數或關鍵詞引數。有時候,我們也希望把引數或關鍵詞引數儲存起來,以備以後使用。有時候,僅僅是為了節省時間。


問題9


下面這些是什麼意思:@classmethod, @staticmethod, @property?


回答背景知識


這些都是裝飾器(decorator)。裝飾器是一種特殊的函式,要麼接受函式作為輸入引數,並返回一個函式,要麼接受一個類作為輸入引數,並返回一個類。@標記是語法糖(syntactic sugar),可以讓你以簡單易讀得方式裝飾目標物件。


@my_decoratordef my_func(stuff):
    do_thingsIs equivalent todef my_func(stuff):
    do_thingsmy_func = my_decorator(my_func)


你可以在本網站上找到介紹裝飾器工作原理的教材。


真正的答案


相關推薦

Python面試必須15問題

訪問flyai.club,一鍵建立你的人工智慧專案 譯文 | [email protected]程式設計派 原文 | [email protected]  引言 想找一份Python開發工作嗎?那你很可能得證明自己知道如何

Python面試必須看的15問題

本文由[email protected]程式設計派獨家編譯,轉載請務必註明作者及出處。   引言 想找一份Python開發工作嗎?那你很可能得證明自己知道如何使用Python。下面這些問題涉及了與Python相關的許多技能,問題的關注點主要是語言本身,不是某個特定的包或模組。每一個問題都可以

必須的九大資料技術

Hadoop是大資料領域最流行的技術,但也並不是唯一。還有很多其他技術可用於解決大資料問題。除了Apache Hadoop外,另外9個大資料技術也是必須要了解的。   1.Apache Flink   是一個高效、分散式、基於Java實現的通用大資料分析引擎,它具

Java程式設計師必須的七開源協議介紹

                1、Mozilla Public License MPL License,允許免費重發布、免費修改,但要求修改後的程式碼版權歸軟體的發起者。這種授權維護了商業軟體的利益,,它要求基於這種軟體得修改無償貢獻版權給該軟體。這樣,圍繞該軟體得所有程式碼得版權都集中在發起開發人得手中。

QThread必須的幾函式

概述     如果想對Qt中的QThread有個更加深刻的瞭解,必須要知道這幾個重要的函式,現在就一一介紹下。 函式介紹 屬性 返回值 函式體 功能 stati

關於備份,你必須的內容

二周 增量 進行 允許 文件 例如 簡便 價值 發現 冷備份:也被稱為離線備份,是指在關閉應用並且應用不能更新的狀況下進行的數據的完整備份 手動備份:要備份到其它磁盤上(避免本地故障,數據丟失) 自動備份:首次完整備份,以後備份為增量備份(例如:一個月備份一次,第一周為完整

JMeter學習(三十)non-gui模式執行 必須的一些資訊

必須要了解的一些資訊 既然是要通過non-gui模式執行,那麼我們就不得不去了解下在non-gui模式下jmeter命令的引數,下面是Jmeter官方文件中列出來的一些引數,中文註釋部分為我加入的解釋 -h, --help print usage inform

安卓專案實戰之與UI那點事:圖片適配你必須的知識點

1,mipmap和drawable的區別 在Android4.2以上的版本中,提供了對mipmaps的支援,如果你用Andorid Studio開發Android程式會發現Android Studio自動幫你建立了幾個mipmaps資料夾,很多人每次新建一個工程的時候,總是先把mipma

移動開發必須的易盾加固生態

本文由作者餘寶虹授權網易雲社群釋出。 移動開發和服務端開發不一樣,移動開發打包後的程式碼安裝在使用者的手機上,這樣一來就為黑客提供了分析的便利,主要存在下面幾個比較大的風險:1 APK被逆向破解,去掉會員,計費等功能導致公司經濟損失,甚至被二次打包為他人做嫁衣;2 APK自身資料儲存和服務端通訊過程中存在極

資料庫的四種隔離級別,程式設計師必須

資料庫提供了四種事務隔離級別, 不同的隔離級別採用不同的鎖類開來實現.  READ UNCOMMITTED(未提交讀) 幻想讀、不可重複讀和髒讀都允許。一個會話可以讀取其他事務未提交的更新結果,如

(轉)從事前端開發必須的CSS原理

 從事Web前端開發的人都與CSS打交道很多,有的人也許不知道CSS是怎麼去工作的,寫出來的CSS瀏覽器是怎麼樣去解析的呢?當這個成為我們提高CSS水平的一個瓶頸時,是否應該多瞭解一下呢?   一、瀏覽器的發展與CSS   網頁瀏覽器主要通過 HTTP 協議連線網頁伺服

CSS3中動畫TRANSFORM必須的SKEW變化原理

transform是CSS3中比較安全的動畫(對於效能來說),其中有一些動畫屬性,來執行不同的變化.今天我們來了解skew的變化原理. skew,其實使用的頻率不是很高,當然也沒有最低.但是往往,一直都不知道他的變化規則.所以使用起來有點摸不著頭腦.動畫上的使用,也就沒

程式猿必須的HTTP協議,今天總結一份關於HTTP請求的結構與具體內容

        HTTP協議(超文字傳輸協議):是網際網路上應用最為廣泛的一種網路協議,所有的WWW檔案都必須遵守這個標準。        1、客戶端發起一個HTTP請求,建立一個到伺服器指定埠(預設80)的TCP連線。        2、伺服器在那個埠監聽客戶端發來的請求。

必須的QT特性!

1、signal和slot是必須理解的。否則看QT的幫助文件都成問題。 2、QT的property特性倒不是必需的。不過看看,很有意思。 3、QT由於是跨平臺SDK。因此,它對event的處理並不像MFC或XAPI那樣明顯。但最好能對event filter有一個清晰的概

Android進階你必須的知識:ThreadLocal

我們 結果 view ins 內存泄漏 ngs extends 實現 map 1、ThreadLocal是什麽? ThreadLocal是一個線程內部數據存儲類,通過他可以在指定的線程中存儲數據。存儲後,只能在指定的線程中獲取到存儲的數據,對其他線程來說無法獲取到數據。 2

學習Linq之前必須的擴展方法

lis des ring return 圖片 hide 命名空間 改變 pac 本文主要以下面幾個方面來詳細講解擴展方法:在C#3.0之前沒有擴展方法的狀態(或者你不會使用不知道擴展方法的時候)、擴展方法的語法及怎麽使用、怎麽正確的使用擴展方法; 一、首先

java高併發系列 - 第22天:java中底層工具類Unsafe,高手必須

這是java高併發系列第22篇文章,文章基於jdk1.8環境。 本文主要內容 基本介紹 通過反射獲取Unsafe例項 Unsafe中的CAS操作 Unsafe中原子操作相關方法介紹 Unsafe中執行緒排程相關方法 park和unpark示例 Unsafe鎖示例 Unsafe中保證變數的可見性 Unsafe

選擇轉行學習WEB前端,你必須的5大要點

隨著網際網路開展,網際網路的體系越多越多,越來越雜亂,使用者不能滿意基本功用的需求,對網際網路體會要求越來越高,客戶端與伺服器的互

JSON——IT技術人員都必須的一種資料交換格式

JSON作為目前Web主流的資料交換格式,是每個IT技術人員都必須要了解的一種資料交換格式。尤其是在Ajax和REST技術的大行其道的當今,JSON無疑成為了資料交換格式的首選! 今天大家就和豬哥一起來學習一下JSON的相關知識吧! 一、XML 在講JSON之前,我覺得有必要先帶大家瞭解一下XML(Ext

零基礎轉行學python(學習方法,學習效率,如何就業)你

個人提醒大家幾點  一:盲目的去學  當初我在對於python這個行業什麼都不瞭解的情況下,比如:不知道未來發展趨勢,不知道學習python應該注意哪些初始問題,不知道具體的學習規劃學習路線等等,一味的買書看書,看視訊,到了中期階段萌生放棄的想法,和主要是因為覺得自己越學