Python后端開發(fā)面試總結(jié)
1. is和==的區(qū)別?
is判斷兩個(gè)引用是否指向的是同一個(gè)變量,即內(nèi)存id是否相等,==則是調(diào)用的eq方法,一般是用于判斷值是否相等,也可以重寫eq方法實(shí)現(xiàn)想要的效果。
2. dict與list的查找復(fù)雜度?
dict用hash實(shí)現(xiàn),查找的時(shí)間復(fù)雜度是O(1),list則為O(n)。
3. a/b/c三個(gè)裝飾器依次裝飾函數(shù)fun(),裝飾器的執(zhí)行順序?
注意裝飾器函數(shù)本身一般有兩層,在裝飾的時(shí)候外層和內(nèi)層順序是相反的,詳情可以參考這邊文章python 多個(gè)裝飾器的調(diào)用順序。
4. 如何運(yùn)行一個(gè)字符串?
eval和exec。
5. Python多線程能否充分利用CPU多核心,為什么?
這里回答的是GIL相關(guān)的東西,可深可淺,自己把握~
6. 什么是上下文管理器?如何實(shí)現(xiàn)?
廣泛意義上來說,上下文是指程序運(yùn)行的環(huán)境,Python中常見于打開文件或網(wǎng)絡(luò)連接,其實(shí)就是with關(guān)鍵字,如:
with open("test.txt") as file:
print(file.read())
可以確保文件在最后會(huì)被關(guān)閉,只要對(duì)一個(gè)對(duì)象實(shí)現(xiàn)了enter和exit函數(shù),就可以構(gòu)造自己的上下文管理器了
7. 同步/異步/阻塞/非阻塞都是什么?
感覺直接解釋概念不好解釋,這里我回答的思路是舉例子,異步說白了就是任務(wù)不需要同步進(jìn)行,比如用爬蟲爬取一個(gè)數(shù)據(jù),然后再保存數(shù)據(jù),接下來再去爬另一個(gè)數(shù)據(jù),這是同步;異步就是爬蟲不用等著數(shù)據(jù)保存好,爬完一個(gè)直接去爬另一個(gè),數(shù)據(jù)保存的事情交給別的邏輯去慢慢處理;阻塞和非阻塞也是基于此的,同步的情況下會(huì)阻塞爬蟲,爬蟲需要等待數(shù)據(jù)的保存.(非專業(yè)解釋)
8. 如何判斷兩個(gè)浮點(diǎn)數(shù)是否相等?
之前完全沒想過這個(gè)的問題,我的回答就是按一個(gè)差不多的精度去比較,比如到小數(shù)點(diǎn)第幾位之前都是相等的,就認(rèn)為兩個(gè)數(shù)相等,或者M(jìn)ath模塊里可能有什么方法可以去精確對(duì)比,當(dāng)時(shí)是這么回答的,現(xiàn)在查了一下基本也是這個(gè)思路,Math模塊中有一個(gè)isclose函數(shù)用來判斷兩個(gè)浮點(diǎn)數(shù)的值是否接近或相等.
9. MySQL的索引一般是怎么實(shí)現(xiàn)的?
B-Tree(一般是B+Tree)和Hash,然后再簡(jiǎn)單介紹一下。
10. 對(duì)于Flask的實(shí)現(xiàn)有了解嗎?
只知道WSGI,其余的不清楚,暫時(shí)還沒去深入看Flask的源碼。
Part 二
1. 一個(gè)木棍任意截成三段,圍成三角形的概率?
咩咩咩?不知道。(回來查了是25%,具體可以自行搜索,反正脫離數(shù)學(xué)N年是無論如何都想不出來的)。
2. 一個(gè)函數(shù)RAND7()隨機(jī)返回1~7,使用它構(gòu)造一個(gè)RAND10()函數(shù)隨機(jī)返回10。
一開始寫了個(gè)函數(shù)如下:
def rand10():
a = rand7() + 3/10
b = rand7() - 4
if b < 0:
b = 0
return a + b
也是腦袋抽了,想得太簡(jiǎn)單,這個(gè)rand10雖然能返回1~10的隨機(jī)數(shù),但每個(gè)數(shù)出現(xiàn)的概率不是1/10,后面時(shí)間快到了檢查的時(shí)候才反應(yīng)過來。正確的思路是:
def rand10():
while 1:
res = (rand7()-1)*7+rand7() \# res等概率隨機(jī)1~49
if res < 40: \# 只取出0~39共40個(gè)數(shù),每個(gè)數(shù)出現(xiàn)的概率也是相等的
return res % 10 \+ 1 \# 隨機(jī)輸出1~10
3. 把一段JAVA代碼改成Python,并增加單元測(cè)試。
JAVA代碼本身很簡(jiǎn)單,即使沒學(xué)過也能看懂,改后的Python代碼如下:
class MyClass:
__current = 0
def next(self):
MyClass.__current += 1
return MyClass.__current
但是對(duì)于單元測(cè)試則僅限于聽過的地步,需要用到unittest,好像也有別的模塊。
4. 給定一個(gè)數(shù)組,按奇數(shù)在前升序,偶數(shù)在后降序排列,一行代碼實(shí)現(xiàn)。
沒啥好說的,一行代碼必然是列表生成式,假設(shè)數(shù)組是nums,代碼如下:
sorted(\[n for n in nums if n % 2\]) \+ sorted(\[n for n in nums if not n % 2\], reverse=True)
5. 實(shí)現(xiàn)單例。
單例就是說一個(gè)class只能有一個(gè)instance,實(shí)現(xiàn)的方法有很多,例如改寫new方法:
class Singleton(object):
_instance = None
def \_\_new\_\_(cls, \*args, \*\*kw):
if not cls._instance:
cls.\_instance = super(Singleton, cls).\_\_new__(cls, \*args, \*\*kw)
return cls._instance
6. 有一個(gè)問答平臺(tái),每個(gè)用戶對(duì)一個(gè)問題最多只能回答一次,同一個(gè)問題最多只能對(duì)一個(gè)答案點(diǎn)贊;1)設(shè)計(jì)合適的數(shù)據(jù)庫結(jié)構(gòu);2)寫出SQL獲取點(diǎn)贊數(shù)最多的10個(gè)問題;
我平時(shí)也就用數(shù)據(jù)庫查數(shù)據(jù),在設(shè)計(jì)數(shù)據(jù)庫上沒有深入研究,因此的我答案就簡(jiǎn)單寫了有哪些表,字段分別是什么,至于題中的條件限制,就交由后臺(tái)的程序邏輯去處理,而不是在數(shù)據(jù)庫設(shè)計(jì)層面去限制。因?yàn)槭亲约涸O(shè)計(jì)的表結(jié)構(gòu),SQL本身也就不難。
7. 設(shè)計(jì)一個(gè)棧,實(shí)現(xiàn)pop/push及max方法,要求能在O(1)時(shí)間內(nèi)取得最大值。
LeetCode原題啊!list怎么能O(1)取得最大值呢,無非是空間換時(shí)間,每push一個(gè)數(shù)就同時(shí)記錄當(dāng)前的最大值。
8. 手寫快排。
呵呵。
其他針對(duì)簡(jiǎn)歷的提問
1. 你的網(wǎng)站,你覺得如果訪問量上去了,最先出現(xiàn)瓶頸問題的點(diǎn)是哪?怎么優(yōu)化?
我答的是數(shù)據(jù)庫,因?yàn)楹枚嗖槐匾蛘呖梢允褂镁彺娴牡胤揭差l繁操作數(shù)據(jù)庫,而且是使用的ORM,但之前從哪看到ORM不能確保對(duì)應(yīng)的SQL語句是最優(yōu)的,因此可以嘗試使用原生SQL或者增加Redis緩存。
2. 如果要擴(kuò)展后臺(tái)服務(wù)器,需要怎么做?
(話說這不是運(yùn)維的工作么。。。)呃,就是增加服務(wù)器啊,然后前面加一層負(fù)載均衡,把請(qǐng)求分配給不同的服務(wù)器.(那不同的服務(wù)器怎么使用你的Session?)再加個(gè)Session服務(wù)器。
3. 我看你平時(shí)刷編程題,有遇到什么有意思的題目嗎?
LeetCode才開始刷,就舉了兩道Codewars上的題目,我也真是傻了,真的舉了兩道有意思(但自己沒做好)的題。
其他就無非是一些為什么想做后端開發(fā)之類的問題了,個(gè)人感覺題目大部分也挺簡(jiǎn)單的,我的表現(xiàn)也算中規(guī)中矩吧,但面試官說我要進(jìn)一步加強(qiáng)基礎(chǔ)知識(shí),具體哪方面(數(shù)據(jù)庫、網(wǎng)絡(luò)協(xié)議、還是Python本身)又語焉不詳。