1.以下代碼輸出為:
list1 = {'1':1,'2':2} list2 = list1 list1['1'] = 5 sum = list1['1'] + list2['1'] print(sum)
解析:10
print('HelloWorld!') print('__name__value: ', __name__) def main(): print('This message is from main function') if __name__ =='__main__': main()
print_module.py的代碼如下:
import print_func print("Done!")
運行print_module.py程序,結果是:
Hello World! __name__ value: print_module Done!
解析:
A _foo 不能直接用於’from module import *’ B __foo解析器用_classname__foo來代替這個名字,以區別和其他類相同的命名 C __foo__代表python里特殊方法專用的標識 D __foo 可以直接用於’from module import *’
編碼:decode()
解碼:encode()
url編碼:urllib.quote()
解碼過程(與編碼過程相反):
解碼 url -> utf-16 -> gbk
A 使用recvfrom()接收TCP數據
B 使用getsockname()獲取連接套接字的遠程地址
C 使用connect()初始化TCP服務器連接
D 服務端使用listen()開始TCP監聽
解析:
sk.recv(bufsize[,flag]):接受套接字的數據。數據以字符串形式返回,bufsize指定最多可以接收的數量。flag提供有關消息的其他信息,通常可以忽略。
sk.connect(address):連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
sk.listen(backlog):開始監聽傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數量。
import copy a = [1, 2, 3, 4, ['a', 'b']] b = a c = copy.copy(a) d = copy.deepcopy(a) a.append(5) a[4].append('c')
a == [1,2, 3, 4, ['a', 'b', 'c'], 5]
b == [1,2, 3, 4, ['a', 'b', 'c'], 5]
c == [1,2, 3, 4, ['a', 'b', 'c']]
d == [1,2, 3, 4, ['a', 'b', ‘c’]]
解析:
首先我們看看看b的情況,b實際上和a指向的是同一個值,就好比人的大名和小名,只是叫法不同,但還是同一個人
接下來再看看c的情況,c的情況和a.copy()的情況是一樣的,都是我們所謂的淺拷貝(淺復制),淺拷貝只會拷貝父對象,不會拷貝子對象,通俗的說就是只會拷貝到第二層
8.請說明裝飾器的作用?
裝飾器的本質上是一個python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象,他經常用於有切面需求的場景,比如,插入日志,性能測試,事務處理,緩存,權限校驗等場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用,概括的講,裝飾器的作用就是為了已經存在的對象添加額外的功能。
常見的裝飾器:類裝飾器,函數裝飾器
類裝飾器,相比函數裝飾器,類裝飾器具有靈活度大,高內聚,封裝性等優點。
9.樂觀鎖和悲觀鎖的區別?
悲觀鎖:顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖(共享資源每次只給一個線程使用,其他線程阻塞,用完再把資源轉讓給其他線程),傳統的關系型數據庫里邊就用到很多這種鎖機制,比如行鎖,表鎖,讀鎖,寫鎖等,都是在操作之前先上鎖。
樂觀鎖:顧名思義,就是很樂觀,每次去拿數據的時候都會認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新數據,可以使用版本號機制和CAS算法實現。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐率。
兩種鎖的使用場景:
從上邊兩種鎖的介紹,我們知道兩種鎖各有優缺點,樂觀鎖適用於多讀的場景,這樣可以省去鎖的開銷,加大系統整個的吞吐率,但是如果是多寫的情況下,一般會產生沖突,這就會導致上層應用會不斷的進行重試,這樣反倒是降低了性能,所以一般多寫的場景下使用悲觀鎖就比較合適。
補充:
CAS算法:
就是一種無鎖算法,無鎖編程,即不使用鎖的情況下實現多線程之間的變量同步,也就是在沒有線程被阻塞的情況下實現變量同步,所以也叫非阻塞同步。
CAS算法涉及到的三個操作數:
- 需要讀寫的內存值V
- 進行比較的值A
- 擬寫入的新值B
當且僅當V的值等於A時,CAS通過原子方式用新值B來更新V的值,否則不會執行任何操作,一般情況下是一個自旋操作,即不斷的重試。
樂觀鎖的缺點:
- ABA問題
- 自選時間CP開銷大
10.什么是協程?與進程和線程有什么區別?
協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制,具有對內核來說不可變的特性。
因為是自主開辟的異步任務,所以也可以叫做纖程,正如一個進程可以擁有多個線程一樣,一個線程也可以擁有多個協程。
協程的目的:在傳統的系統中都是基於每個請求占用一個線程去完成整個的業務邏輯(包括事務),所以系統的吞吐能力取決於每個線程的操作耗時,如果遇到很耗時的IO行為,則整個系統的吞吐立刻下降,因為這個時候線程一直處於阻塞狀態,如果線程很多的時候,會存在很多線程處於空閑狀態(等待該線程執行完才能執行),造成了資源應用不徹底。而協程的目的就是當出現長時間的IO操作的時候,通過讓出目前 的協程調度,執行下一個任務的方式,來消除上下文切換上的開銷。
協程的特點:
線程的切換由操作系統負責調度,協程由用戶自己調度,因此減少了上下文切換,提高了效率。
線程的默認棧大小是1M,而協程更輕量,接近1K,因此可以在相同的內存中開啟更多的協程。
由於在同一個線程上,因此可以避免競爭關系而使用鎖。
適用於被阻塞的,且需要大量開發並發的場景,但是不適用於大量計算的多線程,遇到此種情況,更好使用線程去解決。
協程和進程線程的區別:
- 進程擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,進程由操作系統調度。
- 線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操作系統調度(標准線程是這樣的)。
- 協程和線程一樣共享堆,不共享棧,協程由程序員在協程的代碼里顯示調度。
- 一個應用程序一般對應一個進程,一個進程一般有一個主線程,還有若干個輔助線程,線程之間是平行運行的,在線程里面可以開啟協程,讓程序在特定的時間內運行。
- 協程和線程的區別是:協程避免了無意義的調度,由此可以提高性能,但也因此,程序員必須自己承擔調度的責任,同時,協程也失去了標准線程使用多CPU的能力。
11.python的zip()函數
zip()函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。
如果各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同,利用 * 號操作符,可以將元組解壓為列表。
實例:
1 a = [1,2,3] 2 b = [4,5,6] 3 c = [4,5,6,7,8] 4 zipped = zip(a,b) # 打包為元組的列表 5 [(1, 4), (2, 5), (3, 6)] 6 zip(a,c) # 元素個數與最短的列表一致 7 [(1, 4), (2, 5), (3, 6)] 8 zip(*zipped) # 與 zip 相反,*zipped 可理解為解壓,返回二維矩陣式 9 [(1, 2, 3), (4, 5, 6)]
12.