一巡验、GIL鎖
-
1.1损离、GIL面試題:描述Python GIL的概念, 以及它對python多線程的影響涉兽?編寫一個(gè)多線程抓取網(wǎng)頁的程序招驴,并闡明多線程抓取程序是否可比單線程性能有提升篙程,并解釋原因枷畏。
- Guido的聲明: he language doesn't require the GIL -- it's only the CPython virtual machine that has historically been unable to shed it.
-
1.2、參考答案:
- (1)虱饿、Python語言和GIL沒有半毛錢關(guān)系拥诡。僅僅是由于歷史原因在Cpython虛擬機(jī)(解釋器),難以移除GIL氮发。
- (2)渴肉、GIL:全局解釋器鎖。每個(gè)線程在執(zhí)行的過程都需要先獲取GIL爽冕,保證同一時(shí)刻只有一個(gè)線程可以執(zhí)行代碼仇祭。
- (3)、線程釋放GIL鎖的情況: 在IO操作等可能會(huì)引起阻塞的system call之前,可以暫時(shí)釋放GIL,但在執(zhí)行完畢后,必須重新獲取GIL Python 3.x使用計(jì)時(shí)器(執(zhí)行時(shí)間達(dá)到閾值后颈畸,當(dāng)前線程釋放GIL)或Python 2.x乌奇,tickets計(jì)數(shù)達(dá)到100
- (4)、Python使用多進(jìn)程是可以利用多核的CPU資源的眯娱。
- (5)礁苗、多線程爬取比單線程性能有提升,因?yàn)橛龅絀O阻塞會(huì)自動(dòng)釋放GIL鎖
二徙缴、淺拷貝
2.1试伙、淺拷貝是對于一個(gè)對象的頂層拷貝,簡單的理解是:拷貝了引用于样,并沒有拷貝內(nèi)容疏叨。
-
2.2、 看一個(gè)最簡單的淺拷貝
最簡單的淺拷貝
以上:a 與 b 的內(nèi)存地址相同穿剖,說明了當(dāng)給一個(gè)變量賦值的時(shí)候蚤蔓,其實(shí)就是將數(shù)據(jù)的引用賦值了一份給另外一個(gè)變量,這其實(shí)就是最簡單的淺拷貝,不僅列表是這樣携御,只要是 類似于 xx1 = xx2 的這種基本都是 淺拷貝昌粤,如下:>>> c = {"age":23} >>> d = c >>> id(c) 4527333240 >>> id(d) 4527333240 >>> c["name"] = "王小二" >>> c {'age': 23, 'name': '王小二'} >>> d {'age': 23, 'name': '王小二'}
因?yàn)槎际菧\拷貝,所以只要通過一個(gè)引用進(jìn)行了修改啄刹,那么另外一個(gè)變量就看到的數(shù) 據(jù)也就變化了
-
2.3涮坐、
import copy
模塊中copy.copy()
的使用>>> a = [11,22] >>> b = [33,44] >>> c = [a,b] >>> id(a) 4528760776 >>> id(b) 4528427464 >>> id(c) 4528012488 >>> import copy >>> d = copy.copy(c) >>> id(d) 4528788488 >>> id(d[0]) 4528760776 >>> id(d[1]) 4528427464 >>> a.append(55) >>> c [[11, 22, 55], [33, 44]] >>> d [[11, 22, 55], [33, 44]]
淺拷貝只會(huì)復(fù)制最頂層的那個(gè)列表淺拷貝 只會(huì)復(fù)制最頂層的那個(gè)列表
三、深拷貝
-
3.1誓军、深拷貝是對于一個(gè)對象所有層次的拷貝(遞歸)
>>> a = [11,22] >>> b = copy.deepcopy(a) >>> a [11, 22] >>> b [11, 22] >>> id(a) 4528761928 >>> id(b) 4528933000
以上結(jié)果通過
deepcopy()
確實(shí)將列表a
中所有的數(shù)據(jù)的引用copy
了袱讹,而不是只拷貝了a
指向的列表的引用,看如下,a的數(shù)據(jù)發(fā)生變化的時(shí)候,b并不會(huì)發(fā)生變化>>> a.append(55) >>> a [11, 22, 55] >>> b [11, 22]
-
3.2捷雕、進(jìn)一步理解 深拷貝
進(jìn)一步理解 深拷貝
深拷貝: 我個(gè)人理解其實(shí)是:深拷貝后與原來的對象沒有任何關(guān)系了椒丧,不管原來的對象如何變化,都不再會(huì)影響到深拷貝后的對象
四救巷、拷貝的其他方式
-
4.1壶熏、分片表達(dá)式 可以賦值一個(gè)序列
>>> a = [11,22] >>> b = [33,44] >>> c = [a,b] >>> d = c[:] >>> id(c) 4528760776 >>> id(d) 4528932936 >>> id(c[0]) 4528933000 >>> id(d[0]) 4528933000 >>> a [11, 22] >>> a.append(55) >>> c [[11, 22, 55], [33, 44]] >>> d [[11, 22, 55], [33, 44]]
d=c[:]與d=copy.copy(c)一樣 屬于淺拷貝d=c[:]
與d=copy.copy(c)
一樣 屬于 淺拷貝 -
4.2、字典的copy方法可以拷貝一個(gè)字典
字典的copy方法可以拷貝一個(gè)字典
五浦译、注意點(diǎn)
-
5.1棒假、淺拷貝對不可變類型和可變類型的copy不同
-
copy.copy 對于
可變類型
,會(huì)進(jìn)行淺拷貝>>> a = [11,22] >>> b = copy.copy(a) >>> id(a) 4528932552 >>> id(b) 4528932680 >>> a.append(33) >>> a [11, 22, 33] >>> b [11, 22]
解釋一下大家的對于
a
變化精盅,而b
不變化的問題,因?yàn)閎拷貝的是a里面11帽哑,22
引用的指向,當(dāng)a添加 33的時(shí)候叹俏,而11妻枕,22
引用的指向并沒有發(fā)生變化,所以并不會(huì)發(fā)生變化 -
copy.copy 對于
不可變類型
粘驰,不會(huì)拷貝屡谐,僅僅是指向>>> a = (11,22,33) >>> b = copy.copy(a) >>> id(a) 4528768632 >>> id(b) 4528768632
-
如果c是元組,那么copy時(shí)會(huì)晴氨,僅僅是元組的引用copy,而 deepcopy依然是深copy,即遞歸copy所有
>>> a = [11,22] >>> b = [33,44] >>> c = (a,b) >>> d = copy.copy(c) >>> id(c) 4528885256 >>> id(d) 4528885256 >>> a.append(55) >>> c ([11, 22, 55], [33, 44]) >>> d ([11, 22, 55], [33, 44]) >>> e = copy.deepcopy(c) >>> id(c) 4528885256 >>> id(e) 4528885448 >>> a.append(66) >>> c ([11, 22, 55, 66], [33, 44]) >>> e ([11, 22, 55], [33, 44]) >>>
-
-
5.2康嘉、copy.copy和copy.deepcopy的區(qū)別
-
copy.copy
>>> a = [11,22] >>> b = (a,) >>> c = [b,] >>> >>> d = copy.copy(c) >>> >>> c [([11, 22],)] >>> d [([11, 22],)] >>> a.append(33) >>> c [([11, 22, 33],)] >>> d [([11, 22, 33],)] >>> id(c) 4528932936 >>> id(d) 4528012488 >>> id(c[0]) 4528434200 >>> id(d[0]) 4528434200
copy.copyd = c # 讓d這個(gè)變量指向c指向的空間,d = copy.copy(c) # 復(fù)制所有c指向的數(shù)據(jù)到一個(gè)新的空間籽前,但是不會(huì)遞歸copy
-
copy.deepcopy
>>> a = [11,22] >>> b = (a,) >>> c = [b] >>> >>> d = copy.deepcopy(c) >>> >>> c [([11, 22],)] >>> d [([11, 22],)] >>> >>> id(c) 4528932680 >>> id(d) 4528761928 >>> >>> id(c[0]) 4528913040 >>> id(d[0]) 4528913096 >>> >>> a.append(33) >>> >>> c [([11, 22, 33],)] >>> d [([11, 22],)] >>>
copy.deepcopy
-