python高級面試總結

1.線程、進程、協程
這個問題被問的概率相當之大,其實多線程,多進程,在實際開發中用到的很少,除非是那些對項目性能要求特別高的,有的開發工作幾年了,也確實沒用過,你可以這麼回答,給他扯扯什麼是進程,線程(cpython中是僞多線程)的概念就行,實在不行你就說你之前寫過下載文件時,用過多線程技術,或者業餘時間用過多線程寫爬蟲,提升效率。

進程:一個運行的程序(代碼)就是一個進程,沒有運行的代碼叫程序,進程是系統資源分配的最小單位,進程擁有自己獨立的內存空間,所以進程間數據不共享,開銷大。

線程: 調度執行的最小單位,也叫執行路徑,不能獨立存在,依賴進程存在一個進程至少有一個線程,叫主線程,而多個線程共享內存(數據共享,共享全局變量),從而極大地提高了程序的運行效率。

協程:是一種用戶態的輕量級線程,協程的調度完全由用戶控制。協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。

協程三種方式:

(1)使用yield 來實現協程
(2)使用greenlet 模塊,通過switch來切換不同的代碼塊協程運行
(3)使用gevent 模塊實現協程,打猴子補丁,遇到耗時操作自動切換

2.多線程解決資源競爭問題的方式(線程同步方式)

鎖機制(Lock,RLock可重入鎖)、信號量、condiction條件判斷、同步隊列、event對象

線程是非獨立的,同一個進程裏線程是數據共享的,當各個線程訪問數據資源時會出現競爭狀態即:數據幾乎同步會被多個線程佔用,造成數據混亂 ,即所謂的線程不安全那麼怎麼解決多線程競爭問題?-- 鎖。
鎖的好處:
確保了某段關鍵代碼(共享數據資源)只能由一個線程從頭到尾完整地執行能解決多線程資源競爭下的原子操作問題。
鎖的壞處:
阻止了多線程併發執行,包含鎖的某段代碼實際上只能以單線程模式執行,效率就大大地下降了
鎖的致命問題:死鎖。

鎖(Lock)是 Python 提供的對線程控制的對象。有互斥鎖、可重入鎖。

若干子線程在系統資源競爭時,都在等待對方對某部分資源解除佔用狀態,結果是誰也不願先解鎖,互相干等着,程序無法執行下去,這就是死鎖。GIL 鎖(有時候,面試官不問,你自己要主動說,增加 b 格,儘量別一問一答的尬聊,不然最後等到的一句話就是:你還有什麼想問的麼?)
GIL 鎖 全局解釋器鎖(只在 cpython 裏纔有)作用:限制多線程同時執行,保證同一時間只有一個線程執行,所以 cpython 裏的多線程其實是僞多線程!

所以Python裏常常使用協程技術來代替多線程,協程是一種更輕量級的線程,進程和線程的切換時由系統決定,而協程由我們程序員自己決定,而模塊 gevent 下切換是遇到了耗時操作纔會切換。
三者的關係:進程裏有線程,線程裏有協程。

3.進程之間怎麼共享全局變量?
進程是系統進行資源分配的獨立單位,在以前的python版本中,進程間的數據交互只能通過Queue、Pipes等方式來實現,數據無法直接共享。

在Python 3.8中,multiprocessing模塊提供了SharedMemory類,可以在不同的Python進程之間創建共享的內存block。目前支持int、float、str、bytes、bool、None、numpy.ndarray等一部分Python對象。

當然,shared_memory在實際應用中肯定不會如此簡單,

比如SharedMemory.ShareableList和SharedMemory.SharedMemory的使用本身有很多規則和限制、比如需要考慮數據鎖的問題等等,但是共享內存確實爲進程間通訊提供了一個新的解決方案,而且據說其通訊效率也是非常之高的。

4.線程與進程擴展

多進程適合在 CPU 密集型操作(cpu 操作指令比較多,如位數多的浮點運算)。
多線程適合在 IO 密集型操作(讀寫數據操作較多的,比如爬蟲)。

線程是併發,進程是並行;
進程之間相互獨立,是系統分配資源的最小單位,同一個線程中的所有線程共享資源。

並行:同一時刻多個任務同時在運行。
併發:在同一時間間隔內多個任務都在運行,但是並不會在同一時刻同時運行,存在交替執行的情況。

實現並行的庫有:multiprocessing
實現併發的庫有:threading
程序需要執行較多的讀寫、請求和回覆任務的需要大量的 IO 操作,IO 密集型操作使用併發更好。
CPU 運算量大的程序程序,使用並行會更好。

IO 密集型:系統運作,大部分的狀況是 CPU 在等 I/O (硬盤/內存)的讀/寫。
CPU 密集型:大部份時間用來做計算、邏輯判斷等 CPU 動作的程序稱之 CPU 密集型。

5.裝飾器
裝飾器本質上是一個 Python 函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
它經常用於有切面需求的場景。比如:插入日誌、性能測試、事務處理、緩存、權限的校驗等場景有了裝飾器就可以抽離出大量的與函數功能本身無關的雷同代碼併發並繼續使用。

計算裝飾器裝飾所用時間

import time
start = time.time()
def timeit(f):
	print('開始裝飾啦')
 	for i in range(47000):
    	pass
	return f


@timeit  # foo=timeit(foo)
def foo():
	pass

end = time.time()
s = end - start
print(s)

6.閉包
在函數內部再定義一個函數,並且這個函數用到了外邊函數的變量,那麼將這個函數以及用到的一些變量稱之爲閉包。

7.生成器、迭代器的區別?

迭代器是一個更抽象的概念,任何對象,如果它的類有 next 方法和 iter 方法返回自己本身,對於 string、list、dict、tuple 等這類容器對象,使用 for 循環遍歷是很方便的。在後臺 for 語句對容器對象調用 iter()函數,iter()是 python 的內置函數。iter()會返回一個定義了 next()方法的迭代器對象,它在容器中逐個訪問容器內元素,next()也是 python 的內置函數。在沒有後續元素時,next()會拋出一個 StopIteration 異常。

生成器(Generator)是創建迭代器的簡單而強大的工具。它們寫起來就像是正規的函數,只是在需要返回數據的時候使用 yield 語句。每次 next()被調用時,生成器會返回它脫離的位置(它記憶語句最後一次執行的位置和所有的數據值)

區別:生成器能做到迭代器能做的所有事,而且因爲自動創建了iter()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表達式取代列表解析可以同時節省內存。除了創建和保存程序狀態的自動方法,當發生器終結時,還會自動拋出 StopIteration 異常

8.http協議
瀏覽器訪問服務器的過程

用戶輸入網址.
瀏覽器請求DNS服務器, 獲取域名對應的IP地址.
請求連接該IP地址服務器.
發送資源請求. (HTTP協議)
web服務器接收到請求, 並解析請求, 判斷用戶意圖.
獲取用戶想要的資源.
將資源返回給web服務器程序.
web服務器程序將資源數據通過網絡發送給瀏覽器.
瀏覽器解析請求的數據並且完成網頁數據的顯示.

擴:

HTTP協議就是超文本傳輸協議(HyperText Transfer Protocol),通俗理解是瀏覽器和web服務器傳輸數據格式的協議,HTTP協議是一個應用層協議。

HTTP協議是基於TCP協議的,發送數據之前需要建立好連接

網絡傳輸-TCP/IP四層模型

鏈路層(數據鏈路層/網絡接口層):包括操作系統中的設備驅動程序、計算機中對應的網絡接口卡.
網絡層:處理分組在網絡中的活動,比如分組的選路.
運輸層:主要爲兩臺主機上的應用提供端到端的通信.
應用層:負責處理特定的應用程序細節.

OSI開放系統互聯(Open System Interconnection)的7層從上到下分別是
7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層

HTTP協議響應報文分爲4部分,每部分之間使用\r\n進行分割

響應行
響應頭
空行(\r\n)
響應體

現在http用的是長連接 1.長度 2.有個標識符
9.tcp與udp的區別

TCP:英文全拼(Transmission Control Protocol)簡稱傳輸控制協議,它是一種面向連接的、可靠的、基於字節流的傳輸層通信協議.
優點:
可靠,穩定
適合傳輸大量數據
缺點:
傳輸速度慢
佔用系統資源高

TCP和UDP區別

TCP面向連接,有3次握手,4次揮手; UDP是不面向連接;
TCP提供可靠的數據傳輸,也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP不保證可靠的數據傳輸,容易出現丟包情況;
TCP需要連接傳輸速度慢,UDP不需要連接傳輸速度快
TCP不支持發廣播;UDP支持發廣播
TCP對系統資源要求較多,UDP對系統資源要求較少。
TCP適合發送大量數據,UDP適合發送少量數據
TCP有流量控制,UDP沒有流量控制

瀏覽器、QQ文件傳輸用的是Tcp

ip地址,協議,端口就可以標識網絡的進程
現在http用的是長連接 1.長度 2.有個標識符

請簡單說一下tcp三次握手和四次揮手?

三次握手過程:
1 首先客戶端向服務端發送一個帶有 SYN 標誌,以及隨機生成的序號 100(0 字節)的報文
2 服務端收到報文後返回一個報文(SYN200(0 字節),ACk1001(字節+1))給客戶端
3 客戶端再次發送帶有 ACk 標誌 201(字節+)序號的報文給服務端
至此三次握手過程結束,客戶端開始向服務端發送數據。

1 客戶端向服務端發起請求:我想給你通信,你準備好了麼?
2 服務端收到請求後迴應客戶端:I’ok,你準備好了麼
3 客戶端禮貌的再次回一下客戶端:準備就緒,咱們開始通信吧!
整個過程跟打電話的過程一模一樣:1 喂,你在嗎 2 在,我說的你聽得到不 3 恩,聽得到(接下來請開始你的表演)
補充:SYN:請求詢問,ACk:回覆,迴應。
四次揮手過程:
由於 TCP 連接是可以雙向通信的(全雙工),因此每個方向都必須單獨進行關閉(這句話纔是精闢,後面四個揮手過程都是其具體實現的語言描述)

四次揮手過程,客戶端和服務端都可以先開始斷開連接
1 客戶端發送帶有 fin 標識的報文給服務端,請求通信關閉
2 服務端收到信息後,回覆 ACK 答應關閉客戶端通信(連接)請求
3 服務端發送帶有 fin 標識的報文給客戶端,也請求關閉通信
4 客戶端迴應 ack 給服務端,答應關閉服務端的通信(連接)請求

1.客戶端向服務端發起關閉連接:我要睡覺了了,88喲
2.服務端收到消息後回覆:好的
3.服務端再次發送請求:我也88喲
4.客戶端收到後回覆:嗯嗯,88吧
服務端收到消息後開始睡覺,客戶端等待幾秒,也開始睡覺。

補:SYN: 表示連接請求 ACK: 表示確認
FIN: 表示關閉連接 seq:表示報文序號 ack: 表示確認序號

10.socket
socket(簡稱 套接字) 是進程間通信的一種方式,它與其他進程間通信的一個主要不同是:

它能實現不同主機間的進程間通信,我們網絡上各種各樣的服務大多都是基於 Socket 來完成通信的
例如我們每天瀏覽網頁、QQ 聊天、收發 email 等等

11.ython3編碼轉換

str->bytes:encode編碼
bytes->str:decode解碼

dumps與loads 項目接口裏用到
dumps:將dict(字典)轉換爲str(字符串)。
loads:用於將str(字符串)轉換爲dict(字典)

12.seo搜索優化

SEO(Search Engine Optimization):漢譯爲搜索引擎優化。是一種方式:利用搜索引擎的規則提高網站在有關搜索引擎內的自然排名。目的是讓其在行業內佔據領先地位,獲得品牌收益。很大程度上是網站經營者的一種商業行爲,將自己或自己公司的排名前移。

搜索引擎優化的技術手段主要有黑帽(black hat)、白帽(white hat)兩大類。通過作弊手法欺騙搜索引擎和訪問者,最終將遭到搜索引擎懲罰的手段被稱爲黑帽,比如隱藏關鍵字、製造大量的meta字、alt標籤等。而通過正規技術和方式,且被搜索引擎所接受的SEO技術,稱爲白帽。

13.***args kwargs
*args 可變參數 用來將參數打包成tuple(元組)給函數體調用 接收多餘的位置參數
**kwargs 字典參數 打包關鍵字參數成dict(字典)給函數體調用 接收多餘的關鍵字參數

注意點:推薦書寫順序
def 函數名(位置a,可變參數*args,默認參數b=2,字典參數**kwargs):
pass
函數名(位置0,數據1,數據2,數據3,…,關鍵字參數b=3,關鍵字參數c=4,關鍵字參數d=5)

14.linux命令
cd ls touch mkdir cat tree more clear pwd cd (cp 路徑/文件名 路徑: 把原指定路徑的文件拷貝到新指定路徑) rm mv

lsof -i : 端口號 查看端口號佔用
kiss -9 殺死佔用端口的進程
ps aux|grep ngnix 查看nginx服務器裏運行的程序

15.http與https的區別
http以及https的概念和區別

HTTPS比HTTP更安全,但是性能更低
HTTP:超文本傳輸協議,默認端口號是80
超文本:是指超過文本,不僅限於文本;還包括圖片、音頻、視頻等文件
傳輸協議:是指使用共用約定的固定格式來傳遞轉換成字符串的超文本內容
HTTPS:HTTP + SSL(安全套接字層),即帶有安全套接字層的超本文傳輸協,默認端口號:443
SSL對傳輸的內容(超文本,也就是請求體或響應體)進行加密

16.斐波那契數列

數列中第一個數爲0,第二個數爲1,其後的每一個數都可由前兩個數相加得到:
0,1,1,2,3,5,8,13,21…
求斐波契那數列第1000項的值

a=0
b=1
for i in range(1000):
    a,b=b,a+b
print(b)

17.實現一個線程安全的單例模式

def Singleton(cls):
instances = {}

def get_instance(*args, **kw):
    if cls not in instances:
        instances[cls] = cls(*args, **kw)
    return instances[cls]

return get_instance

擴展
單例模式:
1.概念:只能創建一個對象
2.代碼核心思想:限制函數或者方法 內部的 某部分 的 執行次數
限制代碼的執行:
1.定義標記,判斷標記
2.第一個調用者使用之後,修改標記
3.關鍵點:在哪兒定義標記 最重要(所有調用者共享的數據)

單例模式的應用場景:
單例模式應用的場景一般發現在以下條件下:
(1)資源共享的情況下,避免由於資源操作時導致的性能或損耗等。如日誌文件,應用配置。
(2)控制資源的情況下,方便資源之間的互相通信。如線程池等。 1.網站的計數器 2.應用配置 3.多線程池 4.數據庫配置,數據庫連接池 5.應用程序的日誌應用…

18.常見的響應狀態碼

200:成功
302:跳轉,新的url在響應的Location頭中給出
303:瀏覽器對於POST的響應進行重定向至新的url
307:瀏覽器對於GET的響應重定向至新的url
403:資源不可用;服務器理解客戶的請求,但拒絕處理它(沒有權限)
404:找不到該頁面
500:服務器內部錯誤
503:服務器由於維護或者負載過重未能應答,在響應中可能可能會攜帶Retry-After響應頭;有可能是因爲爬蟲頻繁訪問url,使服務器忽視爬蟲的請求,最終返回503響應狀態碼

19.開放題馬與賽道問題

1.25匹馬,5條跑道,比賽時不計算時間只計算排名,要選出跑的最快的前3名至少需要幾場比賽
7場,
5場比賽定出每組最快的馬
1場比賽定出每組的名次,本場比賽可定出第一名以及淘汰兩組馬
分別用第一名的組的2,3名和第2名的組的1,2名和第3名組的1名進行1場比賽,定出2,3名
至此比賽完畢

20.python的內存管理機制

Python的內存管理機制:引入計數、垃圾回收(引用計數、標記清除、分代回收)、內存池機制

(Python 內部默認的小塊內存與大塊內存的分界點定在 256 個字節,當申請的內存小於 256 字節時,PyObject_Malloc會在內存池中申請內存;當申請的內存大於 256 字節時,PyObject_Malloc 的行爲將蛻化爲 malloc 的行爲。)

引用計數:

引用計數是一種非常高效的內存管理手段, 當一個 Python 對象被引用時其引用計數增加 1, 當其不再被一個變量引用時則計數減 1. 當引用計數等於 0 時對象被刪除。

21.內存泄露是什麼?如何避免?

指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏並非指內存在物理上的消失,而是應用程序分配某段內存後,由於設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。導致程序運行速度減慢甚至系統崩潰等嚴重後果。

del() 函數的對象間的循環引用是導致內存泄漏的主兇。
不使用一個對象時使用:del object 來刪除一個對象的引用計數就可以有效防止內存泄漏問題。
通過 Python 擴展模塊 gc 來查看不能回收的對象的詳細信息。
可以通過 sys.getrefcount(obj) 來獲取對象的引用計數,並根據返回值是否爲 0 來判斷是否內存泄漏。

22. Python 中 pass 語句的作用是什麼?
在編寫代碼時只寫框架思路,具體實現還未編寫就可以用 pass 進行佔位,使程序不報錯,不會進行任何操作。

23.cookie 和 session 的區別?

1、cookie 數據存放在客戶的瀏覽器上,session 數據放在服務器上。
2、cookie 不是很安全,別人可以分析存放在本地的 cookie 並進行 cookie 欺騙考慮到安全應當使用 session。
3、session 會在一定時間內保存在服務器上。當訪問增多,會比較佔用服務器的性能考慮到減輕服務器性能方面,應當使用 cookie。
4、單個 cookie 保存的數據不能超過 4K,很多瀏覽器都限制一個站點最多保存 20 個 cookie。
5、建議: 將登陸信息等重要信息存放爲 SESSION 其他信息如果需要保留,可以放在 cookie 中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章