在發布《Python程序員面試,這些問題你必須提前準備!》一文后,應廣大程序員朋友的強烈要求,小編就Python程序員面試必備問題整理了一份參考答案,希望能對準備換工作的程序員朋友有所幫助。如對答案有疑問,歡迎留言討論。
小編將這些面試問題大致分為四類:
什么(what)?如何做(how)?說區別/談優勢(difference)以及實踐操作(practice)。
What?
1. 什么是Python?
Python是一種編程語言,它有對象、模塊、線程、異常處理和自動內存管理。可以加入與其他語言的對比。下面是回答這一問題的幾個關鍵點:
a. Python是一種解釋型語言,python代碼在運行之前不需要編譯。
b. Python是動態類型語言,在聲明變量時,不需要說明變量的類型。
c. Python適合面向對象的編程,因為它支持通過組合與繼承的方式定義類。
d. 在Python語言中,函數是第一類對象。
e. Python代碼編寫快,但是運行速度比編譯語言通常要慢。
f. Python用途廣泛,常被用作“膠水語言”,可幫助其他語言和組件改善運行狀況。
g. 使用Python,程序員可以專注于算法和數據結構的設計,而不用處理底層的細節。
2. 什么是Python自省?
python自省是python具有的一種能力,使程序員面向對象的語言所寫的程序在運行時,能夠獲得對象的類python型。Python是一種解釋型語言。為程序員提供了極大的靈活性和控制力。
3. 什么是PEP 8?
PEP8是一種編程規范,內容是一些關于如何讓你的程序更具可讀性的建議。
4. 什么是pickling和unpickling?
Pickle模塊讀入任何Python對象,將它們轉換成字符串,然后使用dump函數將其轉儲到一個文件中——這個過程叫做pickling。反之從存儲的字符串文件中提取原始Python對象的過程,叫做unpickling。
5. 什么是Python裝飾器?
Python裝飾器是Python中的特有變動,可以使修改函數變得更容易。
6. 什么是Python的命名空間?
在Python中,所有的名字都存在于一個空間中,它們在該空間中存在和被操作——這就是命名空間。它就好像一個盒子,每一個變量名字都對應裝著一個對象。當查詢變量的時候,會從該盒子里面尋找相應的對象。
7. 什么是字典推導式和列表推導式?
它們是可以輕松創建字典和列表的語法結構。
8. Lambda函數是什么?
這是一個常被用于代碼中的單個表達式的匿名函數。
9. *args,**kwargs?參數是什么?
如果我們不確定要往函數中傳入多少個參數,或者我們想往函數中以列表和元組的形式傳參數時,那就使要用*args;如果我們不知道要往函數中傳入多少個關鍵詞參數,或者想傳入字典的值作為關鍵詞參數時,那就要使用**kwargs。
10. 什么是Pass語句?
Pass是一個在Python中不會被執行的語句。在復雜語句中,如果一個地方需要暫時被留白,它常常被用于占位符。
11. unittest是什么?
在Python中,unittest是Python中的單元測試框架。它擁有支持共享搭建、自動測試、在測試中暫停代碼、將不同測試迭代成一組,等等的功能。
11. 構造器是什么?
構造器是實現迭代器的一種機制。它功能的實現依賴于yield表達式,除此之外它跟普通的函數沒有兩樣。
12. doc string是什么?
Python中文檔字符串被稱為docstring,它在Python中的作用是為函數、模塊和類注釋生成文檔。
13. 負索引是什么?
Python中的序列索引可以是正也可以是負。如果是正索引,0是序列中的第一個索引,1是第二個索引。如果是負索引,(-1)是最后一個索引而(-2)是倒數第二個索引。
14. 模塊和包是什么?
在Python中,模塊是搭建程序的一種方式。每一個Python代碼文件都是一個模塊,并可以引用其他的模塊,比如對象和屬性。
一個包含許多Python代碼的文件夾是一個包。一個包可以包含模塊和子文件夾。
15. 垃圾回收是什么?
在Python中,為了解決內存泄露問題,采用了對象引用計數,并基于引用計數實現自動垃圾回收。
16. CSRF是什么?
CSRF是偽造客戶端請求的一種攻擊,CSRF的英文全稱是Cross Site Request Forgery,字面上的意思是跨站點偽造請求。
How?
1. 如何讓你的程序更具可讀性?
適當地加入非前導空格,適當的空行以及一致的命名。
2. Python是如何被解釋的?
Python是一種解釋性語言,它的源代碼可以直接運行。Python解釋器會將源代碼轉換成中間語言,之后再翻譯成機器碼再執行。
3. 如何在Python中拷貝一個對象?
如果要在Python中拷貝一個對象,大多時候你可以用copy.copy()或者copy.deepcopy()。但并不是所有的對象都可以被拷貝。
4. 如何用Python刪除一個文件?
使用函數os.remove("file")
5. 如何將一個數字轉換成一個字符串?
你可以使用自帶函數str()將一個數字轉換為字符串。如果你想要八進制或者十六進制數,可以用oct()或hex()。
6. Python是如何進行內存管理的?
Python的內存管理是由私有heap空間管理的。所有的Python對象和數據結構都在一個私有heap中。程序員沒有訪問該heap的權限,只有解釋器才能對它進行操作。為Python的heap空間分配內存是由Python的內存管理模塊進行的,其核心API會提供一些訪問該模塊的方法供程序員使用。Python有自帶的垃圾回收系統,它回收并釋放沒有被使用的內存,讓它們能夠被其他程序使用。
7. 如何實現tuple和list的轉換?
以list作為參數將tuple類初始化,將返回tuple類型
以tuple作為參數將list類初始化,將返回list類型
8. Python里面如何生成隨機數?
在python中用于生成隨機數的模塊是random,在使用前需要import. 如下例子可以酌情列舉:
random.random():生成一個0-1之間的隨機浮點數
random.uniform(a, b):生成[a,b]之間的浮點數
random.randint(a, b):生成[a,b]之間的整數
random.randrange(a, b, step):在指定的集合[a,b)中,以step為基數隨機取一個數
random.choice(sequence):從特定序列中隨機取一個元素,這里的序列可以是字符串,列表,元組等
9. 如何在一個function里面設置一個全局的變量
如果要給全局變量在一個函數里賦值,必須使用global語句。global VarName的表達式會告訴Python, VarName是一個全局變量,這樣Python就不會在局部命名空間里尋找這個變量了
10. Python如何實現單例模式?其他23種設計模式python如何實現?
單例模式主要有四種方法:__new__、共享屬性、裝飾器、import。
其他23種設計模式可基本分為創建型、結構型和行為型模式。
創建模式,提供實例化的方法,為適合的狀況提供相應的對象創建方法。
結構化模式,通常用來處理實體之間的關系,使得這些實體能夠更好地協同工作。
行為模式,用于在不同的實體建進行通信,為實體之間的通信提供更容易,更靈活的通信方法。
各模式的實現可根據其特點編寫代碼(限于篇幅,此處不做示例)
11. 如何判斷單向鏈表中是否有環
首先遍歷鏈表,尋找是否有相同地址,借此判斷鏈表中是否有環。如果程序進入死循環,則需要一塊空間來存儲指針,遍歷新指針時將其和儲存的舊指針比對,若有相同指針,則該鏈表有環,否則將這個新指針存下來后繼續往下讀取,直到遇見NULL,這說明這個鏈表無環。
12. 如何遍歷一個內部未知的文件夾?
常用的有以下這幾種辦法:os.path.walk(),os.walk(),listdir
13. mysql數據庫如何分區、分表?
分表可以通過三種方式:mysql集群、自定義規則和merge存儲引擎。
分區有四類:
RANGE 分區:基于屬于一個給定連續區間的列值,把多行分配給分區。
LIST 分區:類似于按RANGE分區,區別在于LIST分區是基于列值匹配一個離散值集合中的某個值來進行選擇。
HASH分區:基于用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含MySQL 中有效的、產生非負整數值的任何表達式。
KEY 分區:類似于按HASH分區,區別在于KEY分區只支持計算一列或多列,且MySQL 服務器提供其自身的哈希函數。必須有一列或多列包含整數值。
14. 如何對查詢命令進行優化?
a. 應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索。
b. 應盡量避免在 where 子句中對字段進行 null 值判斷,避免使用!=或<>操作符,避免使用 or 連接條件,或在where子句中使用參數、對字段進行表達式或函數操作,否則會導致權標掃描
c. 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
d. 使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
e. 很多時候可考慮用 exists 代替 in
f. 盡量使用數字型字段
g. 盡可能的使用 varchar/nvarchar 代替 char/nchar
h. 任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。
i. 盡量使用表變量來代替臨時表。
j. 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
k. 盡量避免使用游標,因為游標的效率較差。
l. 在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF
m. 盡量避免大事務操作,提高系統并發能力。
n. 盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
15. 如何理解開源?
開源,即開放源代碼。開源誕生于軟件行業,它不僅僅代表軟件源代碼的開放,本身即意味著自由、共享和充分利用資源。開源是一種精神,是一種文化,如今已經成為軟件業發展的大勢所趨。
16. 如何理解MVC/MTV框架?
MVC就是把Web應用分為模型(M),控制器(C)和視圖(V)三層,他們之間以一種插件式的、松耦合的方式連接在一起。MTV模式本質上和MVC是一樣的,也是為了各組件間保持松耦合關系,只是定義上有些許不同。
17. MSSQL的死鎖是如何產生的?
如下是死鎖產生的四個必要條件:
互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,則請求者只能等待,直至占有資源的進程用畢釋放。
請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1占用的資源;P1正在等待P2占用的資源,……,Pn正在等待已被P0占用的資源。
18. Sql注入是如何產生的,如何防止?
程序開發過程中不注意規范書寫sql語句和對特殊字符進行過濾,導致客戶端可以通過全局變量POST和GET提交一些sql語句正常執行。產生Sql注入。下面是防止辦法:
a. 過濾掉一些常見的數據庫操作關鍵字,或者通過系統函數來進行過濾。
b. 在PHP配置文件中將Register_globals=off;設置為關閉狀態
c. SQL語句書寫的時候盡量不要省略小引號(tab鍵上面那個)和單引號
d. 提高數據庫命名技巧,對于一些重要的字段根據程序的特點命名,取不易被猜到的
e. 對于常用的方法加以封裝,避免直接暴漏SQL語句
f. 開啟PHP安全模式:Safe_mode=on;
g. 打開magic_quotes_gpc來防止SQL注入
h. 控制錯誤信息:關閉錯誤提示信息,將錯誤信息寫到系統日志。
i. 使用mysqli或pdo預處理。
19. xxs如何預防?
XSS漏洞難以檢測,但是為了WEB安全仍需要盡力避免:
針對反射型和存儲型XSS,需要服務端和前端共同預防,針對用戶輸入的數據做解析和轉義,對于前端開發而言,則是善于使用escape,針對data URI內容做正則判斷,禁止用戶輸入非顯示信息。
對于DOM XSS,由于造成XSS的原因在于用戶的輸入,因此在前端,需要特別注意用戶輸入源,并對可能造成的XSS的操作需要進行字串轉義。
20. 如何生成共享秘鑰? 如何防范中間人攻擊?
密鑰的生成是通過使用全局配置命令完成的:對于不可輸出密鑰是<crypto key generate rsa label {label string},而對于可輸出密鑰則是<crypto key generate rsa exportable label {label string}>。標記(label)是可選擇的;如果沒有指定標記,那么密鑰名稱將是hostname.domain-name。
對于中間人的攻擊,可以采用如下防范手段:
a. 通過采用動態ARP檢測、DHCP Snooping等控制操作來加強網絡基礎設施
b. 采用傳輸加密
c. 使用CASBs(云訪問安全代理)
d. 創建RASP(實時應用程序自我保護)
e. 阻止自簽名證書
f. 強制使用SSL pinning
g. 安裝DAM(數據庫活動監控)
21. 如何管理不同版本的代碼?
進行版本管理。可舉例告知如何使用Git(或是其他工具)進行追蹤。
Difference
1. 數組和元組之間的區別?
數組在python中叫作列表。列表可以修改,而元組不可以修改,如果元組中僅有一個元素,則要在元素后加上逗號。元組和列表的查詢方式一樣。元組只可讀不可修改,如果程序中的數據不允許修改可用元組。
2. _new_和_init_的區別?
__init__是當實例對象創建完成后被調用的,然后設置對象屬性的一些初始值。
__new__是在實例創建之前被調用的,因為它的任務就是創建實例然后返回該實例,是個靜態方法。
也就是,__new__在__init__之前被調用,__new__的返回值(實例)將傳遞給__init__方法的第一個參數,然后__init__給這個實例設置一些參數。
3. Python中單下劃線和雙下劃綫的區別?
"單下劃線" 開始的成員變量叫做保護變量,意思是只有類對象和子類對象自己能訪問到這些變量;
"雙下劃線" 開始的是私有成員,意思是只有類對象自己能訪問,連子類對象也不能訪問到這個數據。
4. 淺拷貝與深拷貝的區別是?
在python中,對象賦值實際上是對象的引用。淺拷貝,沒有拷貝子對象,所以原始數據改變,子對象會改變,而深拷貝,包含對象里面的自對象的拷貝,所以原始對象的改變不會造成深拷貝里任何子元素的改變。
5. 使用裝飾器的單例和使用其他方法的單例,在后續使用中,有何區別?
Import方法改變了類本身,new方法,但是只是把所有實例對象共享屬性,每次產生一個新對象。算作偽單例,共享屬性方法實例化了許多個相同屬性。所以,裝飾器方法最為實用。
6. 多進程與多線程的區別?
a. 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。
b. 線程的劃分尺度小于進程,使得多線程程序的并發性高。
c. 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
d. 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
e. 從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
7. select和epoll的區別?
a. select實現需要自己不斷輪詢所有fd集合,直到設備就緒,期間可能要睡眠和喚醒多次交替。而epoll其實也需要調用epoll_wait不斷輪詢就緒鏈表,期間也可能多次睡眠和喚醒交替,但是它是設備就緒時,調用回調函數,把就緒fd放入就緒鏈表中,并喚醒在epoll_wait中進入睡眠的進程。雖然都要睡眠和交替,但是select在“醒著”的時候要遍歷整個fd集合,而epoll在“醒著”的時候只要判斷一下就緒鏈表是否為空就行了,這節省了大量的CPU時間。
b. select每次調用都要把fd集合從用戶態往內核態拷貝一次,并且要把current往設備等待隊列中掛一次,而epoll只要一次拷貝,而且把current往等待隊列上掛也只掛一次(在epoll_wait的開始,注意這里的等待隊列并不是設備等待隊列,只是一個epoll內部定義的等待隊列)。這也能節省不少的開銷。
8. TCP和UDP的區別?邊緣觸發和水平觸發的區別?
a. 基本區別:
基于連接與無連接
TCP要求系統資源較多,UDP較少;
UDP程序結構較簡單
流模式(TCP)與數據報模式(UDP);
TCP保證數據正確性,UDP可能丟包
TCP保證數據順序,UDP不保證
b. 編程中的區別
socket()的參數不同
UDP Server不需要調用listen和accept
UDP收發數據用sendto/recvfrom函數
TCP:地址信息在connect/accept時確定
UDP:在sendto/recvfrom函數中每次均 需指定地址信息
UDP:shutdown函數無效
9. HTTP連接:get和post的區別?
GET請求,請求的數據會附加在URL之后,以?分割URL和傳輸數據,多個參數用&連接。URL的編碼格式采用的是ASCII編碼,而不是uniclde,即是說所有的非ASCII字符都要編碼之后再傳輸。
POST請求:POST請求會把請求的數據放置在HTTP請求包的包體中。上面的item=bandsaw就是實際的傳輸數據。
因此,GET請求的數據會暴露在地址欄中,而POST請求則不會。
10. varchar與char的區別?
char 長度是固定的,不管你存儲的數據是多少他都會都固定的長度。而varchar則處可變長度但他要在總長度上加1字符,這個用來存儲位置。所以在處理速度上char要比varchar快速很多,但是對費存儲空間,所以對存儲不大,但在速度上有要求的可以使用char類型,反之可以用varchar類型。
11. BTree索引和hash索引的區別?
Hash 索引因其結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節點到枝節點,最后才能訪問到頁節點這樣多次的IO訪問,所以 Hash 索引的查詢效率要遠高于 B-Tree 索引。但也有如下明顯的缺點:
a. Hash 索引僅僅能滿足"=","IN"和"<=>"查詢,不能使用范圍查詢。
b. Hash 索引無法被用來避免數據的排序操作。
c. Hash 索引不能利用部分索引鍵查詢。
d. Hash 索引在任何時候都不能避免表掃描。
e. Hash 索引遇到大量Hash值相等的情況后性能并不一定就會比B-Tree索引高。
12. primary key和unique的區別?
a. 作為Primary Key的域/域組不能為null,而Unique Key可以。
b. 在一個表中只能有一個Primary Key,而多個Unique Key可以同時存在。
C. 邏輯設計上講,Primary Key一般在邏輯設計中用作記錄標識,這也是設置Primary Key的本來用意,而Unique Key只是為了保證域/域組的唯一性。
13. ecb和cbc模式有什么區別?
ECB:是一種基礎的加密方式,密文被分割成分組長度相等的塊(不足補齊),然后單獨一個個加密,一個個輸出組成密文。
CBC:是一種循環模式,前一個分組的密文和當前分組的明文異或操作后再加密,這樣做的目的是增強破解難度。ECB和CBC的加密結果是不一樣的,兩者的模式不同,而且CBC會在第一個密碼塊運算時加入一個初始化向量。
14. 對稱加密與非對稱加密的區別?
對稱加密,需要對加密和解密使用相同密鑰的加密算法。由于其速度快,對稱性加密通常在消息發送方需要加密大量數據時使用。所以,對稱性加密也稱為密鑰加密。
而非對稱加密算法需要兩個密鑰:公開密鑰和私有密鑰。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那么只有用對應的公開密鑰才能解密。
15. Xrange和range的區別?
range([start,] stop[, step]),根據start與stop指定的范圍以及step設定的步長,生成一個序列。xrange 用法與 range 完全相同,所不同的是生成的不是一個list對象,而是一個生成器。要生成很大的數字序列的時候,用xrange會比range性能優很多,因為不需要一上來就開辟一塊很大的內存空間。range會直接生成一個list對象,而xrange則不會直接生成一個list,而是每次調用返回其中的一個值。
16. os與sys模塊的區別?
前者提供了一種方便的使用操作系統函數的方法。后者提供訪問由解釋器使用或維護的變量和與解釋器進行交互的函數。
17. NoSQL和關系數據庫的區別?
a. SQL數據存在特定結構的表中;而NoSQL則更加靈活和可擴展,存儲方式可以省是JSON文檔、哈希表或者其他方式。
b. 在SQL中,必須定義好表和字段結構后才能添加數據,例如定義表的主鍵(primary key),索引(index),觸發器(trigger),存儲過程(stored procedure)等。表結構可以在被定義之后更新,但是如果有比較大的結構變更的話就會變得比較復雜。在NoSQL中,數據可以在任何時候任何地方添加,不需要先定義表。
c. SQL中如果需要增加外部關聯數據的話,規范化做法是在原表中增加一個外鍵,關聯外部數據表。而在NoSQL中除了這種規范化的外部數據表做法以外,我們還能用如下的非規范化方式把外部數據直接放到原數據集中,以提高查詢效率。缺點也比較明顯,更新審核人數據的時候將會比較麻煩。
d. SQL中可以使用JOIN表鏈接方式將多個關系數據表中的數據用一條簡單的查詢語句查詢出來。NoSQL暫未提供類似JOIN的查詢方式對多個數據集中的數據做查詢。所以大部分NoSQL使用非規范化的數據存儲方式存儲數據。
e. SQL中不允許刪除已經被使用的外部數據,而NoSQL中則沒有這種強耦合的概念,可以隨時刪除任何數據。
f. SQL中如果多張表數據需要同批次被更新,即如果其中一張表更新失敗的話其他表也不能更新成功。這種場景可以通過事務來控制,可以在所有命令完成后再統一提交事務。而NoSQL中沒有事務這個概念,每一個數據集的操作都是原子級的。
g. 在相同水平的系統設計的前提下,因為NoSQL中省略了JOIN查詢的消耗,故理論上性能上是優于SQL的。
Practice
這種實踐操作類題目比較豐富多樣,如下幾類比較常見:
1. 補充缺失的代碼
例如:
1
2
3
4
5
6
7
8
|
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 |
2. 下面這段代碼的輸出結果是什么?請解釋。
例如:
1
|
list1 = [ 10 , 'a' ]list2 = [ 123 ]list3 = [ 10 , 'a' ] |
新的默認列表只在函數被定義的那一刻創建一次。當extendList被沒有指定特定參數list調用時,這組list的值隨后將被使用。這是因為帶有默認參數的表達式在函數被定義的時候被計算,不是在調用的時候被計算。
3. 下面的代碼能夠運行么?請解釋?
例如:
能夠運行。當key缺失時,執行DefaultDict類,字典的實例將自動實例化這個數列。
4. 將函數按照執行效率高低排序,并證明自己的答案是正確的。
例如:
按執行效率從高到低排列:f2、f1和f3。要證明這個答案是正確的,你應該知道如何分析自己代碼的性能。Python中有一個很好的程序分析包,可以滿足這個需求。
……
以上就是小編整理的Python面試常用問題和參考答案,供廣大Python程序員參考,希望能提供一點助力。