1. 程式人生 > 實用技巧 >【純乾貨!!!】全網最實用Python面試大全,一共30道題目+答案的純乾貨!!!(建議收藏)

【純乾貨!!!】全網最實用Python面試大全,一共30道題目+答案的純乾貨!!!(建議收藏)

【純乾貨!!!】花費了整整3天,整理出來的全網最實用Python面試大全,一共30道題目+答案的純乾貨,希望大家多多支援,建議 點贊!!收藏!!長文警告,全文共12000+字,涵蓋Python面試可能遇到的所有問題,希望對大家有幫助,不過大家最好不要硬背,實戰大於理論。祝大家面試順利!

對於機器學習演算法工程師而言,Python是不可或缺的語言,它的優美與簡潔令人無法自拔。
那麼你瞭解過Python程式設計面試題嗎?從Python基礎到網頁爬蟲你是否能全方位Hold住?
本文主要從 Python 基礎、高階語句、網頁應用、資料庫和測試等角度出發,
可只關注自己需要的領域。

1、談談對 Python 和其他語言的區別?

答:Python 是一門語法簡潔優美,功能強大無比,應用領域非常廣泛,具有強大完備的第三方庫,他是一門強型別的可移植、可擴充套件,可嵌入的解釋型程式語言,屬於動態語言。和Java相比:Python比Java要簡單.Python是函式為一等公民的語言,而Java是類為一等公民的語言.Python是弱型別語言,而Java是強型別語言。和C相比:對於使用:Python的類庫齊全並且使用簡潔,很少程式碼實現的功能用C可能要很複雜。對於速度:Python的執行速度相較於C,絕對是很慢了.Python和CPython直譯器都是C語言編寫。

2、談談Python 的特點和優點是什麼?

答:Python 是一門動態解釋性的強型別定義語言:編寫時無需定義變數型別;執行時變數型別強制固定;無需編譯,在直譯器環境直接執行。

  • 解釋性:一個用編譯型語言(如 C 或 C++)寫的程式,可以從原始檔轉換到一個計算機使用的語言。這個過程主要通過編譯器完成。當執行程式的時候,我們可以把程式從硬碟複製到記憶體中並且執行。而 Python 語言寫的程式,則不需要編譯成二進位制程式碼,可以直接從原始碼執行程式。在計算機內部,由 Python 直譯器把原始碼轉換成位元組碼的中間形式,然後再把它翻譯成計算機使用的機器語言並執行。
  • 動態性:在執行時可以改變其結構的語言 :例如新的函式、物件、甚至程式碼可以被引進,已有的函式可以被刪除或是其他結構上的變化。動態語言目前非常具有活力。Python便是一個動態語言,除此之外如 PHP 、 Ruby 、 JavaScript 等也都屬於動態語言 。面向物件:面向物件程式設計簡單來說就是基於對 類 和 物件 的使用,所有的程式碼都是通過類和物件來實現的程式設計就是面向物件程式設計!
  • 面向物件的三大特性:封裝、繼承、多型語法簡潔:Python 是一種代表簡單注意思想的語言,閱讀一個良好的 Python 程式,即使是在 Python 語法要求非常嚴格的大環境下,給人的感覺也像是在讀英語段落一樣。
  • 換句話說,Python 程式語言最大的優點之一,是其具有虛擬碼的特質,它可以讓我們在開發 Python 程式時,專注於解決問題,而不是搞明白語言本身。
  • 開源:Python 是開源的,簡單地理解就是,使用者使用 Python 進行開發和釋出自己編寫的程式,不需要支付任何費用,也不用擔心版權問題,即使作為商業用途,Python 也是免費的。開源正在成為軟體行業的一種發展趨勢,現在有很多商業軟體公司都開始將自己的產品變成開源的(例如 Java)。也許,Python 的開源正是它如此優秀的原因之一,因為會有這麼一群人,他們希望看到一個更加優秀的 Python,從而為了這個目標,不斷地對 Python 進行創造,不斷地改進。
  • 可擴充套件性:Python 的可擴充套件性體現為它的模組,Python 具有指令碼語言中最豐富和強大的類庫,這些類庫覆蓋了檔案 I/O、GUI、網路程式設計、資料庫訪問、文字操作等絕大部分應用場景。

3、說說Python直譯器種類以及特點?

答:Python是一門直譯器語言,程式碼想執行,必須通過直譯器執行,Python存在多種直譯器,分別基於不同語言開發,每個直譯器有不同的特點,但都能正常執行Python程式碼。
Python直譯器主要有以下幾個:

  • CPython:官方版本的直譯器:CPython。這個直譯器是用C語言開發的,所以叫CPython。在命令列下執行python就是啟動CPython直譯器。CPython是使用最廣且被的Python直譯器。
  • IPython:IPython是基於CPython之上的一個互動式直譯器,也就是說,IPython只是在互動方式上有所增強,但是執行Python程式碼的功能和CPython是完全一樣的。CPython用>>>作為提示符,而IPython用In [序號]:作為提示符。
  • PyPy:PyPy是另一個Python直譯器,它的目標是執行速度。PyPy採用JIT技術,對Python程式碼進行動態編譯(注意不是解釋),所以可以顯著提高Python程式碼的執行速度。絕大部分Python程式碼都可以在PyPy下執行,但是PyPy和CPython有一些是不同的,這就導致相同的Python程式碼在兩種直譯器下執行可能會有不同的結果。如果你的程式碼要放到PyPy下執行,就需要了解PyPy和CPython的不同點。
  • Jython:Jython是執行在Java平臺上的Python直譯器,可以直接把Python程式碼編譯成Java位元組碼執行。
  • IronPython:IronPython和Jython類似,只不過IronPython是執行在微軟.Net平臺上的Python直譯器,可以直接把Python程式碼編譯成.Net的位元組碼。在這些Python直譯器中,使用廣泛的是CPython 。

4、說說Python面向物件三大特性?

答:Python是一門面向物件的語言。面向物件都有三大特性:封裝、繼承、多型。

下面分別來說說這三大特性:
**封裝:隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。**在python中用雙下劃線開頭的方式將屬性設定成私有的 。好處:1. 將變化隔離;2. 便於使用;3. 提高複用性;4. 提高安全性。
繼承:繼承是一種建立新類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可稱為基類或超類,新建的類稱為派生類或子類。即一個派生類繼承基類的欄位和方法。
繼承也允許把一個派生類的物件作為一個基類物件對待。例如,有這樣一個設計:一個Dog型別的物件派生自Animal類,這是模擬"是一個(is-a)"關係 。python中類的繼承分為:單繼承和多繼承

1 class ParentClass1: #定義父類
2 
3 class ParentClass2: #定義父類
4 
5 class SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClass
6 
7 class SubClass2(ParentClass1,ParentClass2): #python支援多繼承,用逗號分隔開多個繼承的類

多型:一種事物的多種體現形式,函式的重寫其實就是多型的一種體現。Python中,多型指的是父類的引用指向子類的物件 。實現多型的步驟:1、定義新的子類,2、重寫對應的父類方法,3、使用子類的方法直接處理,不呼叫父類的方法。多型的好處:(1)增加了程式的靈活性(2)增加了程式可擴充套件性

5、說說 Python 中有幾種資料型別?

答:Python 中主要有8種資料型別:number(數字)、string(字串)、list(列表)、tuple(元組)、dict(字典)、set(集合)、Boolean(布林值)、None(空值)。

  • 如果對軟體測試有興趣,想了解更多的測試知識,解決測試問題,以及入門指導,
    幫你解決測試中遇到的困惑,我們這裡有技術高手。如果你正在找工作或者剛剛學校出來,
    又或者已經工作但是經常覺得難點很多,覺得自己測試方面學的不夠精想要繼續學習的,
    想轉行怕學不會的,都可以加入我們644956177。
    群內可領取最新軟體測試大廠面試資料和Python自動化、介面、框架搭建學習資料!

6、說說Python中xrange和range的區別?

答:range()和xrange()都是在迴圈中使用,輸出結果一樣。

  • range()返回的是一個list物件,而xrange返回的是一個生成器物件(xrange object)。
  • xrange()則不會直接生成一個list,而是每次呼叫返回其中的一個值,記憶體空間使用極少。因而效能非常好,所以儘量用xrange吧。在python3 中沒有xrange,只有range。range和python2 中的xrange()一樣。

7、Python變數、函式、類的命名規則?

答:

  • (1)不能以數字開頭,不能出現中文。
  • (2)命名以字母開頭,包含數字,字母(區分大小寫),下劃線。
  • (3)不能包含關鍵字,見名知意。

8、說說Python可變與不可變資料型別的區別?

答:Python中看可變與不可變資料型別,主要是看變數所指向的記憶體地址處的值是否會改變 。
Python 的六種標準資料型別:數字、字串、列表、元組、字典、集合。

  • 不可變資料(3個):Number(數字)、String(字串)、Tuple(元組)。
  • 可變資料(3個):List(列表)、Dictionary(字典)、Set(集合)。

9、列舉幾個Python中的標準異常類?

10、說說Python中迭代器和生成器的區別?

答:Python中生成器能做到迭代器能做的所有事,而且因為自動建立了__iter__()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表示式取代列表解析,同時節省記憶體。除了建立和保持程式狀態的自動生成,當發生器終結時,還會自動跑出StopIterration異常。

  • 列表、元組、字典、字串都是可迭代物件。
  • 數字、布林值都是不可迭代的。

11、說說Python字典以及基本操作?

答:字典是 Python 提供的一種常用的資料結構,主要用於存放具有對映關係的資料 。比如儲存某班同學的成績單資料,張三:95分,李四:70分,王五:100分 … ,因為姓名和成績是有關聯的,所以不能單獨用兩個列表來分別儲存,這時候用字典來儲存,再合適不過了 。
字典是一種可變的容器模型,它是通過一組鍵(key)值(value)對組成,這種結構型別通常也被稱為對映,或者叫關聯陣列,也有叫雜湊表的。每個key-value之間用“:”隔開,每組用“,”分割,整個字典用“{}”括起來 ,格式如下所示:

1 dictionary = {key1 : value1, key2 : value2 }

定義字典時,鍵前值後,鍵必須唯一性,值可以不唯一,如果鍵有相同,值則取最後一個;值可以是任何的資料型別,但是鍵必須是不可變的資料型別(數字、字串、元組)。想要訪問字典中的值,只需要將鍵放入方括號裡,如果用字典裡沒有的鍵訪問資料,會輸出錯誤 。

12、說說Python種有幾種字串格式化?

答:Python字串格式化主要有兩種方式:分別為佔位符(%)和format方式 。文末還有2種要介紹,所以總共有4種 。
其中,佔位符(%)方式比較老,而format方式是比較先進的,目前兩者共存。佔位符方式在Python2.x中用的比較廣泛,隨著Python3.x的使用越來越廣,format方式使用的更加廣泛。

13、說說Python多執行緒與多程序的區別?

  • 1、多執行緒可以共享全域性變數,多程序不能
  • 2、多執行緒中,所有子執行緒的程序號相同;多程序中,不同的子程序程序號不同
  • 3、執行緒共享記憶體空間;程序的記憶體是獨立的 。
  • 4、同一個程序的執行緒之間可以直接交流;兩個程序想通訊,必須通過一箇中間代理來實現
  • 5、建立新執行緒很簡單;建立新程序需要對其父程序進行一次克
  • 6、一個執行緒可以控制和操作同一程序裡的其他執行緒;但是程序只能操作子程序兩者最大的不同在於:在多程序中,同一個變數,各自有一份拷貝存在於每個程序中,互不影響;而多執行緒中,所有變數都由所有執行緒共享。

14、說說Python中HTTP常見響應狀態碼?

答:http協議是超文字傳輸協議,是用於從全球資訊網伺服器傳輸文字到本地瀏覽器的傳送協議,是基於tcp/ip通訊協議來傳輸資料的。
HTTP狀態碼(HTTP Status Code)是用以表示網頁伺服器超文字傳輸協議響應狀態的3位數字程式碼。它由 RFC 2616 規範定義的,並得到 RFC 2518、RFC 2817、RFC 2295、RFC 2774 與 RFC 4918 等規範擴充套件。所有狀態碼的第一個數字代表了響應的五種狀態之一。

15、說說Python中猴子補丁是什麼?

答:在Ruby、Python等動態程式語言中,猴子補丁僅指在執行時動態改變類或模組,為的是將第三方程式碼打補丁在不按預期執行的bug或者feature上 。在執行時動態修改模組、類或函式,通常是新增功能或修正缺陷。猴子補丁在程式碼執行時記憶體中發揮作用,不會修改原始碼,因此只對當前執行的程式例項有效。因為猴子補丁破壞了封裝,而且容易導致程式與補丁程式碼的實現細節緊密耦合,所以被視為臨時的變通方案,不是整合程式碼的推薦方式。

16、說說Python中的垃圾回收機制?

答:垃圾回收機制(Garbage Collection:GC)基本是所有高階語言的標準配置之一了,在一定程度上,能優化程式語言的資料處理效率和提高程式設計軟體開發軟體的安全效能 。
在python中的垃圾回收機制主要是以引用****計數為主要手段以標記清除和隔代回收機制為輔的手段 。可以對記憶體中無效資料的自動管理!

17、說說Python中有幾種辦法交換兩個變數的值?

答:交換兩個變數的值方法,這個面試題如果只寫一種當然很簡單,沒什麼可以說的。
今天這個面試是問大家有幾種辦法來實現交換兩個變數的值 。

  • 方法一:通過新新增中間變數temp的方式,這個方法是最簡單的,每個語言都適用。
1     def swap(a,b):
2     temp = a
3     a = b
4     b = temp
5     print(a,b)

  • 方法二:Python獨有的方法,一行程式碼就能搞定,直接將兩個變數放到元組中 。
1    def swap2(a,b):
2     a,b = b,a
3     print(a,b)

  • 方法三:這個方法,是不是很少人想到了,採用加減法來交換 。我們不考慮效率,能達到交換的效果就行 。
1  def swap3(a, b):
2     a = a + b
3     b = a - b
4     a = a - b
5     print(a, b)

  • 方法四:採用異或運算,這個是不是看起來比較高大上。通過按位異或運算來交換兩變數的值,可以減少變數的定義,同時減少計算機對程式碼的解析時間。按位異或運算即計算機會先把十進位制數轉化為二進位制數,並對二進位制數進行從右到左用從1開始編數,然後比較兩個二進位制數值相同位置的數,如果相同結果為0,不同時結果為1 。 “1^1=0 1^0=1 0^0=0”
    如: 1010
    1111
    則結果為 0101
1    def swap4(a,b):
2     a = a ^ b
3     b = a ^ b
4     a = a ^ b
5     print(a,b)

18、說說Python中的6種位運算子?

答:在Python中,按位運算子有左移運算子(<<)、右移運算子(>>)、按位與運算(&)、按位或運算(|)、按位取反運算(~)、異或運算子,其中按位取反運算子為單目運算子 。

19、說說Python中的型別轉換有哪些?

答:在Python處理資料時,不可避免的要使用資料型別之間的轉換。簡單的諸如int、float、string之間的轉換;更有陣列array、列表list之間的轉換。
以下是幾個內建的函式可以執行資料型別之間的轉換。這些函式返回一個新的物件,表示轉換的值。

20、Python中實現二分查詢的2種方法?

答:在Python實現二分查詢法有兩種方法,分別用迴圈和遞迴方式。
二分查詢法:搜尋過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜尋過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半。注意如果要想使用二分查詢,前提必須是元素有序排列 。
迴圈方式

 1 def binary_search_2(alist,item):
 2     """二分查詢---迴圈版本"""
 3     n = len(alist)
 4     first = 0
 5     last = n-1
 6     while first <= last:
 7         mid = (first + last)//2
 8         if alist[mid] ==item:
 9             return True
10         elif item < alist[mid]:
11             last = mid - 1
12         else:
13             first = mid + 1
14     return False
15 if __name__ == "__main__":
16     a = [1,5,6,10,11,13,18,37,99]
17     sorted_list_21 = binary_search_2(a, 18)
18     print(sorted_list_21) //True
19     sorted_list_22 = binary_search_2(a, 77)
20     print(sorted_list_22) //False

遞迴方式

 1 def binary_search(alist,item):
 2     """二分查詢---遞迴實現"""
 3     n = len(alist)
 4     if n > 0:
 5         mid = n//2    #陣列長度的一半中間下標
 6         if item == alist[mid] :
 7             return True   #查詢成功
 8         elif item < alist[mid]:
 9             return binary_search(alist[:mid],item)
10         else:
11             return binary_search(alist[mid+1:], item)
12     else :
13         return False   #失敗
14 if __name__ == "__main__":
15     a = [1,5,6,10,11,13,18,37,99]
16     # print(a)
17     sorted_list_11 = binary_search(a,37)
18     print(sorted_list_11)//True
19     sorted_list_12= binary_search(a, 88)
20     print(sorted_list_12)//False

21、說說Python中的lambda表示式?

答:在Python中lambda表示式也叫匿名函式,即函式沒有具體的名稱。lambda表示式是Python中一類特殊的定義函式的形式,使用它可以定義一個匿名函式。與其它語言不同,Python的lambda表示式的函式體只能有單獨的一條語句,也就是返回值表示式語句。

lambda表示式,通常是在需要一個函式,但是又不想費神去命名一個函式的場合下使用 。lambda所表示的匿名函式的內容應該是很簡單的,如果複雜的話,就重新定義一個函數了。

lambda 表示式允許在一行程式碼中建立一個函式並傳遞。lambda表示式在Python中的優點和缺點: 一方面,Lambda函式的減少了程式碼的行數,方便又簡潔。另一方面,Lambda表示式有諸多限制,不能使用複雜邏輯。

1 add = lambda x, y : x+y
2 num =add(1,2)
3 print("x+y=",num)
4 #結果為:x+y=3

22、說說Python中的反射?

答:在反射機制就是在執行時,動態的確定物件的型別,並可以通過字串呼叫物件屬性、方法、匯入模組,是一種基於字串的事件驅動。通過字串的形式,去模組尋找指定函式,並執行。利用字串的形式去物件(模組)中操作(查詢/獲取/刪除/新增)成員。Python是一門解釋型語言,因此對於反射機制支援很好。
在Python中支援反射機制的函式有getattr()、setattr()、delattr()、exec()、eval()、import,這些函式都可以執行字串。

23、說說Python刪除list裡的重複元素有幾種方法?答:在Python中主要有5種方式,還沒看答案,你能想起幾種呢,面試筆試題經常碰到的一道題 。
使用set函式:set是定義集合的,無序,非重複numList =

1 [1,1,2,3,4,5,4]
2 print(list(set(numList)))
3 #[1, 2, 3, 4, 5]

先把list重新排序,然後從list的最後開始掃描

1 a = [1, 2, 4, 2, 4, 5,]
2 a.sort()
3 last = a[-1]
4 for i in range(len(a) - 2, -1, -1):
5     if last == a[i]:
6         del a[i]
7     else:
8         last = a[i]
9 print(a) #[1, 2, 4, 5]

使用字典函式

1 a=[1,2,4,2,4,]
2 b={}
3 b=b.fromkeys(a)
4 c=list(b.keys())
5 print(c) #[1, 2, 4]

append方式

1 def delList(L):
2     L1 = []
3     for i in L:
4         if i not in L1:
5             L1.append(i)
6     return L1
7 print(delList([1, 2, 2, 3, 3, 4, 5])) #[1, 2, 3, 4, 5]

count + remove方式

1 def delList(L):
2     for i in L:
3         if L.count(i) != 1:
4             for x in range((L.count(i) - 1)):
5                 L.remove(i)
6     return L
7 print(delList([1, 2, 2, 3, 3, 4]))#[1, 2, 3, 4]

24、說說Python中的__new__和__init__的區別?

答:在Python中__new__和__init__具有不同的功能。並且對於Python的新類和舊類而言功能也不同。

  • __new__是在例項建立之前被呼叫的,因為它的任務就是建立例項然後返回該例項物件,是個靜態方法。
  • __init__是當例項物件建立完成後被呼叫的,然後設定物件屬性的一些初始值,通常用在初始化一個類例項的時候。是一個例項方法。
  • 主要區別在於:__new__是用來創造一個類的例項的,而__init__是用來初始化一個例項的。

- 25、說說Python中的help()和dir()函式?

答:在Python中help()和dir()這兩個函式都可以從Python直譯器直接訪問,並用於檢視內建函式的合併轉儲。

  • help()函式:help()函式用於顯示文件字串,還可以檢視與模組,關鍵字,屬性等相關的使用資訊。
  • dir()函式:dir()函式可以列出指定類或模組包含的全部內容(包括函式、方法、類、變數等)

26、說說提高Python執行效率的技巧?

答:不喜歡Python的人經常會吐嘈Python執行太慢。下面給大家介紹幾種種提高python執行效率的方法 。

  • 使用區域性變數:儘量使用區域性變數代替全域性變數:便於維護,提高效能並節省記憶體。一方面可以提高程式效能,區域性變數查詢速度更快;另一方面可用簡短識別符號替代冗長的模組變數,提高可讀性。
  • 使用較新的Python版本:Python已經更新了很多個版本,每個版本的Python都會包含優化內容,使其執行速度優於之前的版本,所以大家記得經常更新版本哦!
  • 先編譯後呼叫:使用eval()、exec()函式執行程式碼時,最好呼叫程式碼物件(提前通過compile()函式編譯成位元組碼),而不是直接呼叫str,可以避免多次執行重複編譯過程,提高程式效能。正則表示式模式匹配也類似,也最好先將正則表示式模式編譯成regex物件(通過re.complie()函式),然後再執行比較和匹配。
  • 採用生成器表示式替代列表解析:列表解析會產生整個列表,對大量資料的迭代會產生負面效應。而生成器表示式則不會,其不會真正建立列表,而是返回一個生成器,在需要時產生一個值(延遲計算),對記憶體更加友好。
  • 關鍵程式碼使用外部功能包:使用 C/C++ 或機器語言的外部功能包處理時間敏感任務,可以有效提高應用的執行效率。這些功能包往往依附於特定的平臺,因此你要根據自己所用的平臺選擇合適的功能包 。比如下面四個功能包:Cython、Pylnlne、PyPy、Pyrex 。
  • 在排序時使用鍵:Python 含有許多古老的排序規則,這些規則在你建立定製的排序方法時會佔用很多時間,而這些排序方法執行時也會拖延程式實際的執行速度。最佳的排序方法其實是儘可能多地使用鍵和內建的 sort() 方法。
  • 優化演算法時間:演算法的時間複雜度對程式的執行效率影響最大,在Python中可以通過選擇合適的資料結構來優化時間複雜度,如list和set查詢某一個元素的時間複雜度分別是O(n)和O(1)。不同的場景有不同的優化方式,總得來說,一般有分治,分支界限,貪心,動態規劃等思想。
  • 迴圈優化:“每種程式語言都會強調需要優化迴圈。當使用Python的時候,你可以依靠大量的技巧使得迴圈執行得更快。
  • 技巧 1:減少迴圈內部不必要的計算
  • 技巧 2:巢狀迴圈中,儘量減少內層迴圈的計算
  • 技巧 3:儘量使用區域性變數
  • 技巧 4:使用 join() 連線字串
  • 交叉編譯你的應用:計算機其實並不理解用來建立現代應用程式的程式語言,計算機理解的是機器語言。所以我們可以用Python語言編寫應用,再以C++這樣的語言執行你的應用,這在執行的角度來說,是可行的。Nuitka是一款有趣的交叉編譯器,能將你的Python程式碼轉化成C++程式碼。這樣,你就可以在native模式下執行自己的應用,而無需依賴於直譯器程式。你會發現自己的應用執行效率有了較大的提高,但是這會因平臺和任務的差異而有所不同。

- 27、Python中的單例模式有幾種實現方式?

答:單例模式(Singleton Pattern)是一種常用的軟體設計模式,該模式的主要目的是確保某一個類只有一個例項存在。在 Python 中,你可以想出幾種種方法來實現單例模式呢?筆試題中,手寫單例模式,也是經常碰到的,所以都要掌握下!
1)使用模組實現:Python 的模組就是天然的單例模式,因為模組在第一次匯入時,會生成 .pyc 檔案,當第二次匯入時,就會直接載入 .pyc 檔案,而不會再次執行模組程式碼。因此,我們只需把相關的函式和資料定義在一個模組中,就可以獲得一個單例物件了。如果我們真的想要一個單例類,可以考慮這樣做:

1 #test1.py
2 class Singleton(object):
3     def foo(self):
4         pass
5 singleton = Singleton()
6 
7 #test2.py
8 from test1 import singleton

2)用__new__特殊方法實現class Singleton:

1     def __new__(cls, *args, **kwargs):
2         if not hasattr(cls, '_instance'):
3             cls._instance = super(Singleton, cls).__new__(cls)
4         return cls._instance
5     def __init__(self, name):
6         self.name = name
7 s1 = Singleton('IT圈')
8 s2= Singleton('程式IT圈')
9 print(s1 == s2) # True

3)使用裝飾器實現def singleton(cls):

 1     _instance = {}
 2     def inner(*args, **kwargs):
 3         if cls not in _instance:
 4             _instance[cls] = cls(*args, **kwargs)
 5         return _instance[cls]
 6     return inner
 7 @singleton
 8 class Singleton:
 9     def __init__(self, name):
10         self.name = name
11 s1 = Singleton('IT圈')
12 s2= Singleton('程式IT圈')
13 print(s1 == s2) # True

4)類裝飾器實現class Singleton:

    def __init__(self, cls):
        self._cls = cls
        self._instance = {}

    def __call__(self, *args):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls(*args)
        return self._instance[self._cls]
@Singleton
class Singleton:
    def __init__(self, name):
        self.name = name
s1 = Singleton('IT圈')
s2= Singleton('程式IT圈')
print(s1 == s2) # True
5)使用元類實現方式class Singleton1(type):
 1 def __init__(self, *args, **kwargs):
 2         self.__instance = None
 3         super(Singleton1, self).__init__(*args, **kwargs)
 4 
 5     def __call__(self, *args, **kwargs):
 6         if self.__instance is None:
 7             self.__instance = super(Singleton1, self).__call__(*args, **kwargs)
 8         return self.__instance
 9 
10 class Singleton(metaclass=Singleton1):
11     def __init__(self, name):
12         self.name = name
13 s1 = Singleton('IT圈')
14 s2= Singleton('程式IT圈')
15 print(s1 == s2) # True

28、Python實現自省的方法有哪些?

答:自省是一種自我檢查行為。在計算機程式設計中,自省是指這種能力:檢查某些事物以確定它是什麼、它知道什麼以及它能做什麼。自省向程式設計師提供了極大的靈活性和控制力。
說的更簡單直白一點:自省就是面向物件的語言所寫的程式在執行時,能夠知道物件的型別。一句可以概況為:執行時能夠獲知物件的型別。
Python實現自省有很多方法,常用的有

  • type(),判斷物件型別dir(), 帶引數時獲得該物件的所有屬性和方法;不帶引數時,返回當前範圍內的變數、方法和定義的型別列表
  • help() , 用於檢視函式或模組用途的詳細說明
  • isinstance(),判斷物件是否是已知型別issubclass(),判斷一個類是不是另一個類的子類
  • hasattr(),判斷物件是否包含對應屬性
  • getattr(),獲取物件屬性
  • setattr(), 設定物件屬性
  • id(): 用於獲取物件的記憶體地址
  • callable():判斷物件是否可以被呼叫。

- 29、簡述一下爬蟲的步驟?

  • 確定需求;
  • 確定資源;
  • 通過url獲取網站的返回資料;
  • 定位資料;
  • 儲存資料。

- 30、遇到的反爬蟲策略以及解決方法?

  • 通過headers反爬蟲:自定義headers,新增網頁中的headers資料。
  • 基於使用者行為的反爬蟲(封IP):可以使用多個代理IP爬取或者將爬取的頻率降低。
  • 動態網頁反爬蟲(JS或者Ajax請求資料):動態網頁可以使用 selenium + phantomjs 抓取。
  • 對部分資料加密處理(資料亂碼):找到加密方法進行逆向推理。
    常見的反爬蟲和應對方法有:
  • 基於使用者行為,同一個ip段時間多次訪問同一頁面 利用代理ip,構建ip池
  • 請求頭裡的user-agent 構建user-agent池(作業系統、瀏覽器不同,模擬不同使用者)
  • 動態載入(抓到的資料和瀏覽器顯示的不一樣),js渲染 模擬ajax請求,返回json形式的資料
  • selenium / webdriver 模擬瀏覽器載入
  • 對抓到的資料進行分析
  • 加密引數欄位 會話跟蹤【cookie】 防盜鏈設定【Referer】
  • 如果對軟體測試有興趣,想了解更多的測試知識,解決測試問題,以及入門指導,
    幫你解決測試中遇到的困惑,我們這裡有技術高手。如果你正在找工作或者剛剛學校出來,
    又或者已經工作但是經常覺得難點很多,覺得自己測試方面學的不夠精想要繼續學習的,
    想轉行怕學不會的,都可以加入我們644956177。
    群內可領取最新軟體測試大廠面試資料和Python自動化、介面、框架搭建學習資料!
    以後遇到更多的問題會加更,祝大家面試順利!共勉。