1. 程式人生 > >史上最全python面試題詳解 (二)(附帶詳細答案(關注、持續更新))

史上最全python面試題詳解 (二)(附帶詳細答案(關注、持續更新))

23、re的match和search區別?

re.match()從開頭開始匹配string。 
re.search()從anywhere 來匹配string。

# 多行模式
>>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match >>> re.search('^X', 'A\nB\nX', re.MULTILINE) # Match <_sre.SRE_Match object at ...>

24、什麼是正則的貪婪匹配

1 如:String str="abcaxc
"; 2   Patter p="ab.*c"; 3   貪婪匹配:正則表示式一般趨向於最大長度匹配,也就是所謂的貪婪匹配。如上面使用模式p匹配字串str,結果就是匹配到:abcaxc(ab.*c)。 4   非貪婪匹配:就是匹配到結果就好,就少的匹配字元。如上面使用模式p匹配字串str,結果就是匹配到:abc(ab.*c)。

25、def func(a,b=[]) 這種寫法有什麼坑?

def func(a,b=[]):
    b.append(a)
    print(b)
func(1)
func(1)
func(1)
func(1)

看下結果

  [1]
  [1, 1]
  [1, 1, 1]
  [1, 1, 1, 1]

函式的第二個預設引數是一個list,當第一次執行的時候例項化了一個list,第二次執行還是用第一次執行的時候例項化的地址儲存,所以三次執行的結果就是 [1, 1, 1] ,想每次執行只輸出[1] ,預設引數應該設定為None。

26、如何實現 “1,2,3” 變成 [‘1’,’2’,’3’] ?

1 # encoding: utf-8
2 a = "1,2,3"
3 b = a.split(",")
4 print b

27、如何實現[‘1’,’2’,’3’]變成[1,2,3]?

1 >>>a = ['1', '2', '3']
2 >>>b = [int(i) for
i in a] 3 >>>b

28、a = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ]的區別?

a裡面的元素都是int型別,b中的元素都是元組。

元組只有一個元素,必須要加逗號結尾

29、一行程式碼選出列表裡面的不重複元素

1 b = [1,2,3,2,3,4,1,2]
2 print [i  for i in b if b.count(i)==1]
3 >>>4

30、logging模組的作用?以及應用場景

  日誌是一種可以追蹤某些軟體執行時所發生事件的方法。

不同的應用程式所定義的日誌等級可能會有所差別,分的詳細點的會包含以下幾個等級:

  • DEBUG
  • INFO
  • NOTICE
  • WARNING
  • ERROR
  • CRITICAL
  • ALERT
  • EMERGENCY

 31、請用程式碼簡答實現stack

 1 stack的實現程式碼(使用python內建的list),實現起來是非常的簡單,就是list的一些常用操作
 2 
 3 class Stack(object):
 4     def __init__(self):
 5         self.stack = []
 6 
 7     def push(self, value):    # 進棧
 8         self.stack.append(value)
 9 
10     def pop(self):  #出棧
11         if self.stack:
12             self.stack.pop()
13         else:
14             raise LookupError(‘stack is empty!‘)
15 
16     def is_empty(self): # 如果棧為空
17         return bool(self.stack)
18 
19     def top(self): 
20         #取出目前stack中最新的元素
21         return self.stack[-1]
 1 定義一個頭結點,左邊指向佇列的開頭,右邊指向佇列的末尾,這樣就可以保證我們插入一個元素和取出一個元素都是O(1)的操作,使用這種連結串列實現stack也是非常的方便。實現程式碼如下:
 2 
 3 class Head(object):
 4     def __init__(self):
 5         self.left = None
 6         self.right = None
 7 
 8 class Node(object):
 9     def __init__(self, value):
10         self.value = value
11         self.next = None
12 
13 class Queue(object):
14     def __init__(self):
15         #初始化節點
16         self.head = Head()
17 
18     def enqueue(self, value):
19         #插入一個元素
20         newnode = Node(value)
21         p = self.head
22         if p.right:
23             #如果head節點的右邊不為None
24             #說明佇列中已經有元素了
25             #就執行下列的操作
26             temp = p.right
27             p.right = newnode
28             temp.next = newnode
29         else:
30             #這說明佇列為空,插入第一個元素
31             p.right = newnode
32             p.left = newnode
33 
34     def dequeue(self):
35         #取出一個元素
36         p = self.head
37         if p.left and (p.left == p.right):
38             #說明佇列中已經有元素
39             #但是這是最後一個元素
40             temp = p.left
41             p.left = p.right = None
42             return temp.value
43         elif p.left and (p.left != p.right):
44             #說明佇列中有元素,而且不止一個
45             temp = p.left
46             p.left = temp.next
47             return temp.value
48 
49         else:
50             #說明佇列為空
51             #丟擲查詢錯誤
52             raise LookupError(‘queue is empty!‘)
53 
54     def is_empty(self):
55         if self.head.left:
56             return False
57         else:
58             return True
59 
60     def top(self):
61         #查詢目前佇列中最早入隊的元素
62         if self.head.left:
63             return self.head.left.value
64         else:
65             raise LookupError(‘queue is empty!‘)

 32、常用字串格式化哪幾種?

 1 一、使用%
 2 %s     字串
 3 %c     字元
 4 %d     十進位制(整數)
 5 %i     整數
 6 %u    無符號整數
 7 %o     八進位制整數
 8 %x    十六進位制整數
 9 %X     十六進位制整數大寫
10 %e     浮點數格式1 
11 %E     浮點數格式2 
12 %f     浮點數格式3 
13 %g    浮點數格式4 
14 %G    浮點數格式5 
15 %%     文字% 
16 >>> print("我叫%s,今年%d歲了" % ("小李", 20))
17 我叫小李,今年20歲了
二、通過{}替代%
1、正常使用
>>> print("我叫{},今年{}歲了".format("小李", 20))
我叫小李,今年20歲了
2、還可以通過在括號裡填寫數字,修改格式化的順序
>>> print("我叫{1},今年{0}歲了".format("小李", 20))
我叫20,今年小李歲了
3、通過key取變數
>>> print("我叫{name},今年{age}歲了".format(name="小李", age=20))
我叫小李,今年20歲了
4、傳入物件
>>> class Person:
...     def __init__(self,name,age):
...
...             self.name,self.age = name,age
...     def __str__(self):
...
...             return '我叫{self.name}, 今年{self.age}歲了'.format(self=self)
>>> str(Person('小李',20))
'我叫小李, 今年20歲了'
5、通過下標
>>> person=['小李',20]
>>> '我叫{0[0]}, 今年{0[1]}歲了'.format(person)
'我叫小李, 今年20歲了'

33、簡述 生成器、迭代器、可迭代物件 以及應用場景?

Python可迭代物件(Iterable) 
Python中經常使用for來對某個物件進行遍歷,此時被遍歷的這個物件就是可迭代物件,像常見的list,tuple都是。如果給一個準確的定義的話,就是隻要它定義了可以返回一個迭代器的__iter__方法,或者定義了可以支援下標索引的__getitem__方法(這些雙下劃線方法會在其他章節中全面解釋),那麼它就是一個可迭代物件。

Python迭代器(iterator) 
迭代器是通過next()來實現的,每呼叫一次他就會返回下一個元素,當沒有下一個元素的時候返回一個StopIteration異常,所以實際上定義了這個方法的都算是迭代器。可以用通過下面例子來體驗一下迭代器:

生成器(Generators) 
生成器是構造迭代器的最簡單有力的工具,與普通函式不同的只有在返回一個值的時候使用yield來替代return,然後yield會自動構建好next()iter()

因為迭代器如此普遍,python專門為for關鍵字做了迭代器的語法糖。在for迴圈中,Python將自動呼叫工廠函式iter()獲得迭代器,自動呼叫next()獲取元素,還完成了檢查StopIteration異常的工作。

 1 1.3 定義迭代器 
 2 下面一個例子——斐波那契數列
 3 # -*- coding: cp936 -*-
 4 class Fabs(object):
 5     def __init__(self,max):
 6         self.max = max
 7         self.n, self.a, self.b = 0, 0, 1  #特別指出:第0項是0,第1項是第一個1.整個數列從1開始
 8     def __iter__(self):
 9         return self
10     def next(self):
11         if self.n < self.max:
12             r = self.b
13             self.a, self.b = self.b, self.a + self.b
14             self.n = self.n + 1
15             return r
16         raise StopIteration()
17 
18 print Fabs(5)
19 for key in Fabs(5):
20     print key
21 
22 結果
23 <__main__.Fabs object at 0x01A63090>
24 1
25 1
26 2
27 3
28 5

34、用Python實現一個二分查詢的函式

 1 #!usr/bin/env python  
 2 #encoding:utf-8  
 3 def binary_search(num_list, x):
 4     '''
 5     二分查詢
 6     '''
 7     num_list=sorted(num_list)
 8     left, right = 0, len(num_list)
 9     while left < right:
10         mid = (left + right) / 2
11         if num_list[mid] > x:
12             right = mid
13         elif num_list[mid] < x:
14             left = mid + 1
15         else:
16             return '待查元素{0}在列表中下標為:{1}'.format(x, mid)
17     return  '待查詢元素%s不存在指定列表中'%x
18  
19 if __name__ == '__main__':
20     num_list = [34,6,78,9,23,56,177,33,2,6,30,99,83,21,17]
21     print binary_search(num_list, 34)
22     print binary_search(num_list, 177)
23     print binary_search(num_list, 21)
24     print binary_search(num_list, 211)
25     print binary_search(num_list, 985)
26 》》》
27 待查元素34在列表中下標為:9
28 待查元素177在列表中下標為:14
29 待查元素21在列表中下標為:5
30 待查詢元素211不存在指定列表中
31 待查詢元素985不存在指定列表中

35、談談你對閉包的理解。

 1 #閉包函式的例項
 2 # outer是外部函式 a和b都是外函式的臨時變數
 3 def outer( a ):
 4     b = 10
 5     # inner是內函式
 6     def inner():
 7         #在內函式中 用到了外函式的臨時變數
 8         print(a+b)
 9     # 外函式的返回值是內函式的引用
10     return inner
11 
12 if __name__ == '__main__':
13     # 在這裡我們呼叫外函式傳入引數5
14     #此時外函式兩個臨時變數 a是5 b是10 ,並建立了內函式,然後把內函式的引用返回存給了demo
15     # 外函式結束的時候發現內部函式將會用到自己的臨時變數,這兩個臨時變數就不會釋放,會繫結給這個內部函式
16     demo = outer(5)
17     # 我們呼叫內部函式,看一看內部函式是不是能使用外部函式的臨時變數
18     # demo存了外函式的返回值,也就是inner函式的引用,這裡相當於執行inner函式
19     demo() # 15
20 
21     demo2 = outer(7)
22     demo2()#17

36、os和sys模組的作用

os模組負責程式與作業系統的互動,提供了訪問作業系統底層的介面;

sys模組負責程式與python直譯器的互動,提供了一系列的函式和變數,用於操控python的執行時環境。

 1 os 常用方法
 2 
 3 
 4 os.remove(‘path/filename’) 刪除檔案
 5 
 6 os.rename(oldname, newname) 重新命名檔案
 7 
 8 os.walk() 生成目錄樹下的所有檔名
 9 
10 os.chdir('dirname') 改變目錄
11 
12 os.mkdir/makedirs('dirname')建立目錄/多層目錄
13 
14 os.rmdir/removedirs('dirname') 刪除目錄/多層目錄
15 
16 os.listdir('dirname') 列出指定目錄的檔案
17 
18 os.getcwd() 取得當前工作目錄
19 
20 os.chmod() 改變目錄許可權
21 
22 os.path.basename(‘path/filename’) 去掉目錄路徑,返回檔名
23 
24 os.path.dirname(‘path/filename’) 去掉檔名,返回目錄路徑
25 
26 os.path.join(path1[,path2[,...]]) 將分離的各部分組合成一個路徑名
27 
28 os.path.split('path') 返回( dirname(), basename())元組
29 
30 os.path.splitext() 返回 (filename, extension) 元組
31 
32 os.path.getatime\ctime\mtime 分別返回最近訪問、建立、修改時間
33 
34 os.path.getsize() 返回檔案大小
35 
36 os.path.exists() 是否存在
37 
38 os.path.isabs() 是否為絕對路徑
39 
40 os.path.isdir() 是否為目錄
41 
42 os.path.isfile() 是否為檔案
43 
44 
45 sys 常用方法
46 
47 
48 sys.argv 命令列引數List,第一個元素是程式本身路徑
49 
50 sys.modules.keys() 返回所有已經匯入的模組列表
51 
52 sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細資訊
53 
54 sys.exit(n) 退出程式,正常退出時exit(0)
55 
56 sys.hexversion 獲取Python解釋程式的版本值,16進位制格式如:0x020403F0
57 
58 sys.version 獲取Python解釋程式的版本資訊
59 
60 sys.maxint 最大的Int值
61 
62 sys.maxunicode 最大的Unicode值
63 
64 sys.modules 返回系統匯入的模組欄位,key是模組名,value是模組
65 
66 sys.path 返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值
67 
68 sys.platform 返回作業系統平臺名稱
69 
70 sys.stdout 標準輸出
71 
72 sys.stdin 標準輸入
73 
74 sys.stderr 錯誤輸出
75 
76 sys.exc_clear() 用來清除當前執行緒所出現的當前的或最近的錯誤資訊
77 
78 sys.exec_prefix 返回平臺獨立的python檔案安裝的位置
79 
80 sys.byteorder 本地位元組規則的指示器,big-endian平臺的值是'big',little-endian平臺的值是'little'
81 
82 sys.copyright 記錄python版權相關的東西
83 
84 sys.api_version 直譯器的C的API版本

37、談談你對面向物件的理解?

在我理解,面向物件是向現實世界模型的自然延伸,這是一種“萬物皆物件”的程式設計思想。在現實生活中的任何物體都可以歸為一類事物,而每一個個體都是一類事物的例項。面向物件的程式設計是以物件為中心,以訊息為驅動,所以程式=物件+訊息。

面向物件有三大特性,封裝、繼承和多型。

封裝就是將一類事物的屬性和行為抽象成一個類,使其屬性私有化,行為公開化,提高了資料的隱祕性的同時,使程式碼模組化。這樣做使得程式碼的複用性更高。

繼承則是進一步將一類事物共有的屬性和行為抽象成一個父類,而每一個子類是一個特殊的父類--有父類的行為和屬性,也有自己特有的行為和屬性。這樣做擴充套件了已存在的程式碼塊,進一步提高了程式碼的複用性。

如果說封裝和繼承是為了使程式碼重用,那麼多型則是為了實現介面重用。多型的一大作用就是為了解耦--為了解除父子類繼承的耦合度。如果說繼承中父子類的關係式IS-A的關係,那麼介面和實現類之之間的關係式HAS-A。簡單來說,多型就是允許父類引用(或介面)指向子類(或實現類)物件。很多的設計模式都是基於面向物件的多型性設計的。

總結一下,如果說封裝和繼承是面向物件的基礎,那麼多型則是面向物件最精髓的理論。掌握多型必先了解介面,只有充分理解接口才能更好的應用多型。

38、面向物件深度優先和廣度優先是什麼?

請關注,未完待續!