(給資料分析與開發加星標,提升資料技能)
來源:kenwoodjw,轉自:機器之心
對於機器學習演演算法工程師而言,Python是不可或缺的語言,它的優美與簡潔令人無法自拔。那麼你瞭解過Python程式設計面試題嗎?從Python基礎到網頁爬蟲你是否能全方位Hold住?今天,機器之心為讀者們推薦一個Github專案。
在這個專案中,作者 kenwoodjw 準備了近 300 道 Python 面試題,同時還包含解決方案與程式碼。作者主要從 Python 基礎、高階陳述句、網頁應用、資料庫和測試等角度提問,讀者可只關註自己需要的領域。目前該專案已經完成了很多基礎和高階面試題,本文主要摘取一些 Python 面試題供大家參考。
專案地址:
https://github.com/kenwoodjw/python_interview_question
總體而言,專案有近300道面試題。雖然該專案剛開始建立,但很多Python面試題都已經提供瞭解決方案。如下所示為面試題示例:
本文截取了一些面試題及解決方案:
-
Python 基礎
-
檔案操作
-
模組與包
-
資料型別
-
企業面試題
-
Python 高階
-
設計樣式
-
系統程式設計
如果希望瞭解機器學習面試題,可閱讀:春招已近,這份GitHub萬星的ML演演算法面試大全請收下
Python 基礎
什麼是 Python?根據Python 建立者 Guido van Rossum 所言,Python是一種高階程式語言,其設計的核心理念是程式碼的易讀性,以及允許程式設計者透過若干行程式碼輕鬆表達想法創意。實際上,很多開發者選擇學習 Python 的首要原因是其程式設計的優美性,用它編碼和表達想法非常自然。
檔案操作
1.若有一個jsonline格式的檔案file.txt,大小約為10K,我們的處理方式為:
def get_lines():
l = []
with open('file.txt', 'rb') as f:
for eachline in f:
l.append(eachline)
return l
if __name__ == '__main__':
for e in get_lines():
process(e) #處理每一行資料
現在要處理一個大小為10G的file.txt檔案,但是記憶體只有4G。如果在只修改get_lines 函式而其他程式碼保持不變的情況下,應該如何實現?需要考慮的問題都有那些?
def get_lines():
l = []
with open('file.txt','rb') as f:
data = f.readlines(60000)
l.append(data)
yield l
要考慮的問題有:記憶體只有4G,無法一次性讀入10G檔案。而分批讀入資料要記錄每次讀入資料的位置,且分批每次讀取得太小會在讀取操作上花費過多時間。
模組與包
2.如何輸入日期, 判斷這一天是這一年的第幾天?
import datetime
def dayofyear():
year = input("請輸入年份: ")
month = input("請輸入月份: ")
day = input("請輸入天: ")
date1 = datetime.date(year=int(year),month=int(month),day=int(day))
date2 = datetime.date(year=int(year),month=1,day=1)
return (date1-date2).days+1
資料型別
3.如何反轉字串”aStr”?
print("aStr"[::-1])
4.下麵程式碼的輸出結果將是什麼?會報錯嗎?
list = ['a','b','c','d','e']
print(list[10:])
程式碼將輸出[],並不會產生IndexError 錯誤。如果嘗試用超出成員的個數的index來獲取某個串列的成員,那就會報錯。例如,嘗試獲取 list[10] 和之後的成員,會導致IndexError。然而當我們嘗試獲取串列的切片時,開始的index超過成員個數並不會產生IndexError,而是僅僅傳回一個空串列。因為並不會報錯,所以這種Bug很難追蹤到。
5.請寫出一段Python程式碼,實現刪除list裡面的重覆元素?
l1 = ['b','c','d','c','a','a']
l2 = list(set(l1))
print(l2)
用list類的sort方法可以保證順序不變:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print(l2)
也可以這樣寫:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']
l2 = sorted(set(l1), key=l1.index)
print(l2)
也可以用遍歷:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']
l2 = []
for i in l1:
if not i in l2:
l2.append(i)
print(l2)
企業面試題
6.設計實現遍歷目錄與子目錄,抓取.pyc檔案
第一種方法:
import os
def getFiles(dir, suffix):
res = []
for root, dirs, files in os.walk(dir):
for filename in files:
name, suf = os.path.splitext(filename)
if suf == suffix:
res.append(os.path.join(root, filename))
print(res)
getFiles("./", '.pyc')
第二種方法:
import os
def pick(obj):
try:
if obj.[-4:] == ".pyc":
print(obj)
except:
return None
def scan_path(ph):
file_list = os.listdir(ph)
for obj in file_list:
if os.path.isfile(obj):
pick(obj)
elif os.path.isdir(obj):
scan_path(obj)
if __name__ == '__main__':
path = input('輸入目錄')
scan_path(path)
7.如何反轉一個整數,例如-123–> -321?
class Solution(object):
def reverse(self, x):
if -10 10:
return x
str_x = str(x)
if str_x[0] != "-":
str_x = str_x[::-1]
x = int(str_x)
else:
str_x = str_x[1:][::-1]
x = int(str_x)
x = -x
return x if -2147483648 2147483647 else 0
if __name__ == '__main__':
s = Solution()
reverse_int = s.reverse(-120)
print(reverse_int)
Python高階
Python高階包含很多重要的模組,例如函式、類和實體、系統程式設計、正則運算式、網路程式設計等等。根據這些高階屬性,Python可用於資料科學、網頁開發、機器學習等等。
設計樣式
8.對設計樣式的理解,簡述你瞭解的設計樣式?
設計樣式是為我們經常會碰到的一些程式設計問題構建的可重用解決方案,它是總結性和經最佳化的。一個設計樣式並不像一個類或一個庫那樣能夠直接作用於我們的程式碼,反之,設計樣式更為高階,它是一種在特定情形下實現的方法模板。常見的是工廠樣式和單例樣式。
單例樣式應用的場景一般發現在以下條件下: 資源共享的情況下,避免由於資源操作時導致的效能或損耗等,如日誌檔案,應用配置。控制資源的情況下,方便資源之間的互相通訊。
9.生成器和迭代器的區別?
迭代器是一個更抽象的概念,任何物件,如果它的類有 next 方法和 iter 方法傳回自己本身,它就是可迭代的。對於 string、list、dict、tuple 等這類容器物件,使用for迴圈遍歷是很方便的,for 陳述句實際上會對容器物件呼叫 iter() 函式。iter() 會傳回一個定義了 next() 方法的迭代器物件,它在容器中逐個訪問容器內元素,在沒有後續元素時,next()會丟擲一個StopIteration異常。
生成器(Generator)是建立迭代器的簡單而強大的工具。它們寫起來就像是正規的函式,只是在需要傳回資料的時候使用yield陳述句。生成器能做到迭代器能做的所有事,而且因為自動建立iter()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器運算式取代串列解析可以同時節省記憶體。除了建立和儲存程式狀態的自動方法,當發生器終結時,還會自動丟擲StopIteration異常。
10.對裝飾器的理解,你能寫出一個計時器裝飾器,它能記錄函式的執行時間嗎?
裝飾器本質上是一個Python函式,它可以讓其他函式在不需要做任何程式碼變動的前提下增加額外功能,裝飾器的傳回值也是一個函式物件。
import time
def timeit(func):
def wrapper():
start = time.clock()
func()
end = time.clock()
print('used:',end-start)
return wrapper
@timeit
def foo():
print('in foo()'foo())
系統程式設計
11.介紹一下你瞭解的行程。
程式執行在作業系統上的一個實體,就稱之為行程。行程需要相應的系統資源:記憶體、時間片、pid。建立行程: 首先要匯入multiprocessing中的Process;建立一個Process物件;建立Process物件時,可以傳遞引數。
p = Process(target=XXX, args=(tuple,), kwargs={key: value})
target = XXX # 指定的任務函式,不用加()
args = (tuple,)
kwargs = {key: value} # 給任務函式傳遞的引數
使用start()啟動行程 結束行程 給子行程指定函式傳遞引數Demo
import os
from mulitprocessing import Process
import time
def pro_func(name, age, **kwargs):
for i in range(5):
print("子行程正在執行中,name=%s,age=%d,pid=%d" % (name, age, os.getpid()))
print(kwargs)
time.sleep(0.2)
if __name__ == "__main__":
# 建立Process物件
p = Process(target=pro_func, args=('小明', 18), kwargs={'m': 20})
# 啟動行程
p.start()
time.sleep(1)
# 1秒鐘之後,立刻結束子行程
p.terminate()
p.join()
12.談談你對多行程、多執行緒、以及協程的理解,專案是否用?
行程:一個執行的程式(程式碼)就是一個行程,沒有執行的程式碼叫程式,行程是系統資源分配的最小單位,行程擁有自己獨立的記憶體空間,所有行程間資料不共享,開銷大。執行緒: cpu排程執行的最小單位,也叫執行路徑,不能獨立存在,依賴行程存在,一個行程至少有一個執行緒,叫主執行緒,而多個執行緒共享記憶體可以極大地提高了程式的執行效率。協程: 是一種使用者態的輕量級執行緒,協程的排程完全由使用者控制,協程擁有自己的暫存器背景關係和棧。協程排程時,將暫存器背景關係和棧儲存到其他地方,在切回來的時候,恢復先前儲存的暫存器背景關係和棧,直接操中棧則基本沒有核心切換的開銷,可以不加鎖的訪問全域性變數,所以背景關係的切換非常快。
關於系統程式設計還有很多問題,例如: