python學習筆記4:基礎(集合,collection系列,深淺拷貝)


轉載至:http://www.cnblogs.com/liu-yao/p/5146505.html

一.集合

1.集合(set):

把不同的元素組成一起形成集合,是python基本的數據類型。集合元素(set elements):組成集合的成員

python的set和其他語言類似, 是一個無序不重復元素集, 基本功能包括關系測試和消除重復元素. 集合對象還支持union(聯合), intersection(交), difference(差)和sysmmetric difference(對稱差集)等數學運算.  

sets 支持 x in set, len(set),和 for x in set。作為一個無序的集合,sets不記錄元素位置或者插入點。因此,sets不支持 indexing, slicing, 或其它類序列(sequence-like)的操作。 

2.集合的創建

1

2

3

4

5

6

7

8

9

10

11

se =  set ([ 11 , 22 , 33 , 44 ])
print (se)
{ 33 , 11 , 44 , 22 }
print ( type (se))
< class  'set' >
或者
>>> se =  { 'liu' , 'yao' }
>>> se
{ 'yao' , 'liu' }
>>> type (se)
< class  'set' >

集合的使用

具體用法:

1.add(添加元素)

1
2
3
>>> se.add( '123' )
>>> se
{ 'yao' , 'liu' , '123' }

2.clear(清空集合)

 

1
2
3
>>> se.clear()
>>> se
set ()

3.copy(淺拷貝)

1
2
3
4
>>> se_1 =  { 'liu' , 'yao' }
>>> se_2 = se_1.copy()
>>> se_2
{ 'yao' , 'liu' }

4.difference差異比較

1
2
3
4
5
6
7
8
>>> se_1 =  { 'liu' , 'yao' , 'shi' , 'shei' }
>>> se_2 =  { 'haode' , 'shi' , 'liu' }
#取出se_2中在se_1所沒有的元素
>>> se_1.difference(se_2)
{ 'yao' , 'shei' }
#取出se_1中在se_2所沒有的元素
>>> se_2.difference(se_1)
{ 'haode' }

5.difference_update差異更新

 

1
2
3
4
5
6
7
>>> se_1
{ 'shi' , 'yao' , 'liu' }
>>> se_2
{ 'shi' , 'liu' , 'haode' }
>>> se_1.difference_update(se_2)
>>> se_1
{ 'yao' }

6.discard移除指定元素

1
2
3
4
5
>>> se_1
{ 'shi' , 'yao' , 'shei' , 'liu' }
>>> se_1.discard( 'shei' )
>>> se_1
{ 'shi' , 'yao' , 'liu' }

7.intersection取交集並且建立新的集合

 

1
2
3
4
>>> se_1={ 'liu' , 'yao' , 'shi' , 'sha' , 'bi' }
>>> se_2={ 'liu' , 'yao' , 'shi' , 'er' , 'bi' }
>>> se_1.intersection(se_2)
{ 'liu' , 'shi' , 'yao' , 'bi' }

8.intersection_update取交集並且更新原來的集合

 

1
2
3
4
5
>>> se_1 = { 'liu' , 'yao' , 'shi' , 'sha' , 'bi' }
>>> se_2 = { 'liu' , 'yao' , 'shi' , 'er' , 'bi' }
>>> se_1.intersection_update(se_2)
>>> se_1
{ 'liu' , 'shi' , 'yao' , 'bi' }

9.isdisjoint判斷沒有交集,沒有返回true,有返回false

 

1
2
3
4
5
6
7
8
9
10
11
>>> se_1={ 'liu' , 'yao' , 'shi' , 'sha' , 'bi' }
>>> se_2={ 'liu' , 'yao' , 'shi' , 'er' , 'bi' }
>>> se_1.isdisjoint(se_2)
False
>>> se_2.isdisjoint(se_1)
False
>>> se_1={ 'liu' , 'yao' }
>>> se_2={ 'liuu' , 'yaoo' }
>>> se_2.isdisjoint(se_1)
True

10.issubset判斷是否為子集

1
2
3
4
5
>>> se_1 =  { 'liu' , 'yao' }
>>> se_2 =  { 'liu' , 'yao' , 'shabi' }
#判斷se_1是否為se_2的子集
>>> se_1.issubset(se_2)
True

11.issuperset判斷是否為父集

1
2
3
4
5
6
7
8
9
>>> se_1 =  { 'liu' , 'yao' }
>>> se_2 =  { 'liu' , 'yao' , 'shabi' }
#判斷se_1是否為se_2的父集
>>> se_1.issuperset(se_2)
False
#判斷se_2是否為se_1的父集
>>> se_2.issuperset(se_1)
True
>>>

12.pop移除集合元素

1
2
3
>>> se_1 =  { 'liu' , 'yao' , 'sha' , 'bi' }
>>> se_1.pop()
'sha'

13.remove刪除指定元素集合

1
2
3
4
5
>>> se_1 =  { 'liu' , 'yao' , 'sha' , 'bi' }
>>> se_1.remove( 'bi' )
>>> se_1
{ 'sha' , 'liu' , 'yao' }
>>>

14.symmetric_difference取兩個集合的差集,並建立新的元素

1
2
3
4
5
6
7
>>> se_1 =  { 'liu' , 'yao' , 'sha' , 'bi' }
>>> se_2 =  { 'liu' , 'yao' , 'shabi' }
>>> se_1.symmetric_difference(se_2)
{ 'sha' , 'shabi' , 'bi' }
>>> b = se_1.symmetric_difference(se_2)
>>> b
{ 'sha' , 'shabi' , 'bi' }

15.symmetric_difference_update取兩個集合的差集,更新原來的集合對象

1
2
3
4
5
>>> se_1 =  { 'liu' , 'yao' , 'sha' , 'bi' }
>>> se_2 =  { 'liu' , 'yao' , 'shabi' }
>>> se_1.symmetric_difference_update(se_2)
>>> se_1
{ 'sha' , 'shabi' , 'bi' }

16.union並集

1
2
3
4
5
6
>>> se_1
{ 'sha' , 'shabi' , 'bi' }
>>> se_2
{ 'shabi' , 'liu' , 'yao' }
>>> se_1.union(se_2)
{ 'yao' , 'sha' , 'shabi' , 'liu' , 'bi' }

17.update更新集合

1
2
3
4
5
>>> se_1
{ 'sha' , 'shabi' , 'bi' }
>>> se_1.update( 'liuyao' )
>>> se_1
{ 'y' , 'o' , 'shabi' , 'bi' , 'u' , 'i' , 'sha' , 'l' , 'a' }

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
old_dict =  {
     "#1" :{ 'hostname' : 'c1' , 'cpu_count' : 2 , 'mem_capicity' : 80  },
     "#2" :{ 'hostname' : 'c1' , 'cpu_count' : 2 , 'mem_capicity' : 80  },
     "#3" :{ 'hostname' : 'c1' , 'cpu_count' : 2 , 'mem_capicity' : 80  }
}
new_dict =  {
     "#1" :{ 'hostname' : 'c1' , 'cpu_count' : 2 , 'mem_capicity' : 800  },
     "#3" :{ 'hostname' : 'c1' , 'cpu_count' : 2 , 'mem_capicity' : 80  },
     "#4" :{ 'hostname' : 'c2' , 'cpu_count' : 2 , 'mem_capicity' : 80  }
}
#獲取old_dict元素
old =  set (old_dict.keys())
print (old)
#獲取new_dict元素
new =  set (new_dict.keys())
print (new)
#要更新的集合元素(交集)
update_set =  old.intersection(new)
print (update_set)
#獲取要刪除的集合元素(差集)
delete_set =  old.difference(new)
print (delete_set)
#獲取要添加的集合元素()
add_set =  new.difference(update_set)
print (add_set)

二.collection系列

 

collections模塊自Python 2.4版本開始被引入,包含了dict、set、list、tuple以外的一些特殊的容器類型,分別是:

OrderedDict類:排序字典,是字典的子類。引入自2.7。

namedtuple()函數:命名元組,是一個工廠函數。引入自2.6。

Counter類:為hashable對象計數,是字典的子類。引入自2.7。

deque:雙向隊列。引入自2.4。

defaultdict:使用工廠函數創建字典,使不用考慮缺失的字典鍵。引入自2.5。

文檔參見:http://docs.python.org/2/library/collections.html

使用的時候需要用import導入collections模塊

1.計數器(counter

Counter類的目的是用來跟蹤值出現的次數。它是一個無序的容器類型,以字典的鍵值對形式存儲,其中元素作為key,其計數作為value。計數值可以是任意的Interger(包括0和負數)。Counter類和其他語言的bags或multisets很相似。

(1)創建

 創建一個空的Counter類

1
2
3
4
5
6
7
8
9
import  collections
c =  collections.Counter() # 創建一個空的Counter類
print (c)
c =  collections.Counter( 'asdfghjjhgfdqwer' )
print (c)
c =  collections.Counter({ 'a' : 4 , 'b' : 2 }) #從一個字典對象創建
print (c)
c =  collections.Counter(a = 4 , b = 2 ) # 從一組鍵值對創建
print (c)

結果:

1
2
3
4
Counter()
Counter({ 'd' : 2 , 'f' : 2 , 'h' : 2 , 'g' : 2 , 'j' : 2 , 's' : 1 , 'a' : 1 , 'r' : 1 , 'q' : 1 , 'e' : 1 , 'w' : 1 })
Counter({ 'a' : 4 , 'b' : 2 })
Counter({ 'a' : 4 , 'b' : 2 })

(2).計數值的訪問

當所訪問的鍵不存在時,返回0,而不是KeyError;否則返回它的計數。

 

1
2
3
4
5
6
7
8
9
>>> import  collections
>>> c =  collections.Counter( 'asdfgdsasdf' )
>>> c[ 'a' ]
2
>>> c[ 'h' ]
0
>>> c[ 's' ]
3
>>>

(3).計數器的更新與減少

1.update()更新

 

1
2
3
4
5
6
>>> c
Counter({ 's' : 3 , 'd' : 3 , 'a' : 2 , 'f' : 2 , 'g' : 1 })
>>> c =  collections.Counter( 'update' )
>>> c.update( 'update' )
>>> c
Counter({ 'a' : 2 , 'e' : 2 , 'd' : 2 , 'p' : 2 , 'u' : 2 , 't' : 2 })

2.subtract()減少

 

1
2
3
4
5
6
7
>>> c =  collections.Counter( 'subtract' )
>>> c
Counter({ 't' : 2 , 'a' : 1 , 'c' : 1 , 'b' : 1 , 's' : 1 , 'r' : 1 , 'u' : 1 })
>>> c.subtract( 'subtract' )
>>> c
Counter({ 'a' : 0 , 'c' : 0 , 'b' : 0 , 's' : 0 , 'r' : 0 , 'u' : 0 , 't' : 0 })
>>>

(4)鍵的刪除

當計數值為0時,並不意味着元素被刪除,刪除元素應當使用del

1
2
3
4
5
6
7
8
>>> c =  collections.Counter( 'abcdcba' )
>>> c[ 'b' ] = 0
>>> c
Counter({ 'a' : 2 , 'c' : 2 , 'd' : 1 , 'b' : 0 })
>>> del  c[ 'a' ]
>>> c
Counter({ 'c' : 2 , 'd' : 1 , 'b' : 0 })
>>>

(5) 迭代器

返回一個迭代器。元素被重復了多少次,在該迭代器中就包含多少個該元素。所有元素按照字母序排序,個數小於1的元素不被包含。

 

1
2
3
4
>>> c =  collections.Counter( 'abcdcba' )
>>> list (c.elements())
[ 'a' , 'a' , 'c' , 'c' , 'b' , 'b' , 'd' ]
>>>

(5)most_common([n])

返回一個TopN列表。如果n沒有被指定,則返回所有元素。當多個元素計數值相同時,按照字母序排列。

 

1
2
3
>>> c =  collections.Counter( 'abcdcba' )
>>> c.most_common()
[( 'a' , 2 ), ( 'c' , 2 ), ( 'b' , 2 ), ( 'd' , 1 )]

(6)淺拷貝

 

1
2
3
4
5
6
7
>>> c =  collections.Counter( 'abcdcba' )
>>> c
Counter({ 'a' : 2 , 'c' : 2 , 'b' : 2 , 'd' : 1 })
>>> cc = c.copy()
>>> cc
Counter({ 'a' : 2 , 'c' : 2 , 'b' : 2 , 'd' : 1 })
>>>

(7)算術與集合操作

+、-、&、|操作也可以用於Counter。其中&和|操作分別返回兩個Counter對象各元素的最小值和最大值。需要注意的是,得到的Counter對象將刪除小於1的元素。

1
2
3
4
5
6
7
8
9
10
>>> c =  collections.Counter(a = 3 , b = 1 )
>>> d =  collections.Counter(a = 1 , b = 2 )
>>> c + d
Counter({ 'a' : 4 , 'b' : 3 })
>>> c - d
Counter({ 'a' : 2 })
>>> c&d
Counter({ 'a' : 1 , 'b' : 1 })
>>> c|d
Counter({ 'a' : 3 , 'b' : 2 })

一些Counter類的常用操作,來源於Python官方文檔

1
2
3
4
5
6
7
8
9
sum (c.values())  # 所有計數的總數
c.clear()  # 重置Counter對象,注意不是刪除
list (c)  # 將c中的鍵轉為列表
set (c)  # 將c中的鍵轉為set
dict (c)  # 將c中的鍵值對轉為字典
c.items()  # 轉為(elem, cnt)格式的列表
Counter( dict (list_of_pairs))  # 從(elem, cnt)格式的列表轉換為Counter類對象
c.most_common()[: - n: - 1 # 取出計數最少的n個元素
c + =  Counter()  # 移除0和負值

2.有序字典(orderedDict )

有序字典繼承字典的一切屬性,只是在順序上是有序的。

1
2
3
4
5
6
>>> import  collections
>>> info =  collections.OrderedDict({ 'name' : 'liuyao' , 'age' : 21 })
>>> info
OrderedDict([( 'age' , 21 ), ( 'name' , 'liuyao' )])
>>> type (info)
< class  'collections.OrderedDict' >
1
2
3
4
5
6
7
8
import  collections
info =  collections.OrderedDict(name = 'liuyao' ,age = '21' ,job = 'IT' )
print  (info)
print  (info.keys())
print  (info.values())
OrderedDict([( 'age' , '21' ), ( 'name' , 'liuyao' ), ( 'job' , 'IT' )])
odict_keys([ 'age' , 'name' , 'job' ])
odict_values([ '21' , 'liuyao' , 'IT' ])

一些功能:

(1).move_to_end將指定的鍵值對從開頭移動到末尾。

 

1
2
3
4
5
>>> import  collections
>>> info =  collections.OrderedDict(name = 'liuyao' ,age = '21' ,job = 'IT' )
>>> info.move_to_end( 'name' )
>>> info
OrderedDict([( 'age' , '21' ), ( 'job' , 'IT' ), ( 'name' , 'liuyao' )])

(2).pop刪除字典鍵值,返回刪除的鍵值的values

1
2
3
4
5
6
>>> info =  collections.OrderedDict(name = 'liuyao' ,age = '21' ,job = 'IT' )
>>> info.pop( 'job' )
'IT'
>>> info
OrderedDict([( 'age' , '21' ), ( 'name' , 'liuyao' )])
>>>

(3).clear清除有序字典的值

1
2
3
4
>>> info =  collections.OrderedDict(name = 'liuyao' ,age = '21' ,job = 'IT' )
>>> info.clear()
>>> info
OrderedDict()

 

1
2
3
4
5
6
7
8
9
10
import  collections
info =  collections.OrderedDict(name = 'liuyao' ,age = '21' ,job = 'IT' )
print  (info)
print  (info.keys())
print  (info.values())
print  (info.items())
OrderedDict([( 'age' , '21' ), ( 'job' , 'IT' ), ( 'name' , 'liuyao' )])
odict_keys([ 'age' , 'job' , 'name' ])
odict_values([ '21' , 'IT' , 'liuyao' ])
odict_items([( 'age' , '21' ), ( 'job' , 'IT' ), ( 'name' , 'liuyao' )])

3.默認字典(defaultdict) 

這里的defaultdict(function_factory)構建的是一個類似dictionary的對象,其中keys的值,自行確定賦值,但是values的類型,是function_factory的類實例,而且具有默認值。比如default(int)則創建一個類似dictionary對象,里面任何的values都是int的實例,而且就算是一個不存在的key, d[key] 也有一個默認值,這個默認值是int()的默認值0.

defaultdict是對字典的類型的補充,他默認給字典的值設置了一個類型。創建一個默認字典,value值類型為列表.dic = collections.defaultdict(list)

例:

 

1
2
3
4
5
6
7
8
import  collections
s =  [( 'yellow' , 1 ), ( 'blue' , 2 ), ( 'yellow' , 3 ), ( 'blue' , 4 ), ( 'red' , 1 )]
 
d =  collections.defaultdict( list )
for  k, v in  s:
     d[k].append(v)
 
list (d.items())

defaultdict可以接受一個內建函數list作為參數。其實呢,list()本身是內建函數,但是再經過更新后,python里面所有東西都是對象,所以list改編成了類,引入list的時候產生一個類的實例。

1
2
3
4
5
6
7
8
import  collections
dic =  collections.defaultdict( list )
dic[ 'k1' ]
print  (dic)
print  (dic.keys())
print  (dic.values())
dic[ 'k1' ].append( 'v1' )
print  (dic.values())

一些具有的方法:

1.copy拷貝

1
2
3
4
5
6
7
8
9
10
import  collections
dic =  collections.defaultdict( list )
dic[ 'k1' ]
dic[ 'k1' ].append( 'v1' )
print  (dic)
dic_1 = dic.copy()
print  (dic_1)
#結果
defaultdict(< class  'list' >, { 'k1' : [ 'v1' ]})
defaultdict(< class  'list' >, { 'k1' : [ 'v1' ]})

4.可命名元組(namedtuple) 

沒有現成的類,用戶需要自行創建相應的類

 

1
2
3
4
5
6
7
8
import  collections
tu =  collections.namedtuple( 'tu' ,[ 'x' , 'y' , 'z' ])  #創建一個類,類名為Point
yao_tu =  tu( 11 , 22 , 33 )
print (yao_tu)
print (yao_tu.x)  #直接通過命名元素去訪問元組對應的元素,
print (yao_tu[1 ])  #等同於上面這種方式,但是沒有上面這種方式可讀性強
print (yao_tu.y)
print (yao_tu.z)

5.雙向隊列(deque)

 

(1)創建一個隊列

1
2
3
import  collections
que =  collections.deque([ 'sb' , 'liu' , 'yao' ])
print  (que)

(2)追加元素到隊列

1
2
3
4
5
6
>>> que.append( 'wo' )
>>> que
deque([ 'sb' , 'liu' , 'yao' , 'wo' ])
>>> que.append([ 'ni' , 'ta' ])
>>> que
deque([ 'sb' , 'liu' , 'yao' , 'wo' , [ 'ni' , 'ta' ]])

(3)追加元素到隊列左側

 

1
2
3
>>> que.appendleft( 'zuo' )
>>> que
deque([ 'zuo' , 'sb' , 'liu' , 'yao' , 'wo' , [ 'ni' , 'ta' ]])

(4)統計元素個數

 

1
2
3
4
5
6
>>> que.appendleft( 'zuo' )
>>> que
deque([ 'zuo' , 'sb' , 'liu' , 'yao' , 'wo' , [ 'ni' , 'ta' ]])
>>> que.appendleft( 'zuo' )
>>> que.count( 'zuo' )
2

(4)清除

 

1
2
3
>>> que.clear()
>>> que
deque([])

(5)extend擴展元素

 

1
2
3
4
5
6
>>> que = collections.deque([ 'sb' , 'liu' , 'yao' ])
>>> que
deque([ 'sb' , 'liu' , 'yao' ])
>>> que.extend([ 'a' , 'b' , 'c' ])
>>> que
deque([ 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' ])

(6)extendleft從左側擴展

 

1
2
3
4
5
>>> que
deque([ 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' , 'zuo3' ])
>>> que.extendleft([ 'zuo4' , 'zuo5' , 'zuo6' ])
>>> que
deque([ 'zuo6' , 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' , 'zuo3' ])

(7)pop刪除

1
2
3
4
5
6
>>> que
deque([ 'zuo6' , 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' , 'zuo3' ])
>>> que.pop()
'zuo3'
>>> que
deque([ 'zuo6' , 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' ])

(8)popleft從左側開始刪除

1
2
3
4
5
6
>>> que
deque([ 'zuo6' , 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' ])
>>> que.popleft()
'zuo6'
>>> que
deque([ 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' ])

(9)reverse順序反轉

 

1
2
3
4
5
>>> que
deque([ 'zuo5' , 'zuo4' , 'sb' , 'liu' , 'yao' , 'a' , 'b' , 'c' , 'zuo1' , 'zuo2' ])
>>> que.reverse()
>>> que
deque([ 'zuo2' , 'zuo1' , 'c' , 'b' , 'a' , 'yao' , 'liu' , 'sb' , 'zuo4' , 'zuo5' ])

(10)remove刪除指定元素

 

1
2
3
4
5
>>> que
deque([ 'zuo2' , 'zuo1' , 'c' , 'b' , 'a' , 'yao' , 'liu' , 'sb' , 'zuo4' , 'zuo5' ])
>>> que.remove( 'sb' )
>>> que
deque([ 'zuo2' , 'zuo1' , 'c' , 'b' , 'a' , 'yao' , 'liu' , 'zuo4' , 'zuo5' ])

(11)rotate將隊列末尾4個元素反轉到隊列左側

1
2
3
4
5
>>> que
deque([ 'zuo5' , 'zuo2' , 'zuo1' , 'c' , 'b' , 'a' , 'yao' , 'liu' , 'zuo4' ])
>>> que.rotate( 4 )
>>> que
deque([ 'a' , 'yao' , 'liu' , 'zuo4' , 'zuo5' , 'zuo2' , 'zuo1' , 'c' , 'b' ])

6.單向隊列 queue(先進先出 FIFO )

(1)創建

1
2
3
4
5
6
>>> import  queue
>>> que =  queue.Queue( 2 )
>>> que
<queue.Queue object  at 0x7f70678ec550 >
>>>
>>> que =  queue.Queue(maxsize = 10 )

queue.Queue類即是一個隊列的同步實現。隊列長度可為無限或者有限。可通過Queue的構造函數的可選參數maxsize來設定隊列長度。如果maxsize小於1就表示隊列長度無限。

(3)放入任務

 

1
2
>>> que.put([ 'a' , 'd' ])
>>> que

調用隊列對象的put()方法在隊尾插入一個項目。put()有兩個參數,第一個item為必需的,為插入項目的值;第二個block為可選參數,默認為
1。如果隊列當前為空且block為1,put()方法就使調用線程暫停,直到空出一個數據單元。如果block為0,put方法將引發Full異常。

(3)從隊列中取值

1
2
3
4
>>> que.put([ 'a' , 'd' ])
>>> que.get()
[ 'a' , 'd' ]
>>>

調用隊列對象的get()方法從隊頭刪除並返回一個項目。可選參數為block,默認為True。如果隊列為空且block為True,get()就使調用線程暫停,直至有項目可用。如果隊列為空且block為False,隊列將引發Empty異常。

(3)返回隊列大小

1
2
>>> que.qsize()
1

(4)判斷隊列為空返回True,反之False

1
2
3
>>> que.empty()
False
>>>

(5)q.full() 如果隊列滿了,返回True,反之False

1
2
3
>>> que.full()
False
>>>

q.full 與 maxsize 大小對應

其他方法:

 

1
2
3
4
5
6
q.get([block[, timeout]]) 獲取隊列,timeout等待時間
q.get_nowait() 相當q.get( False )
非阻塞 q.put(item) 寫入隊列,timeout等待時間
q.put_nowait(item) 相當q.put(item, False )
q.task_done() 在完成一項工作之后,q.task_done() 函數向任務已經完成的隊列發送一個信號
q.join() 實際上意味着等到隊列為空,再執行別的操作

三.深淺拷貝

1.為什么要拷貝?

當進行修改時,想要保留原來的數據和修改后的數據

2.數字字符串 和 集合 在修改時的差異? (深淺拷貝不同的終極原因)

 

在修改數據時:
     數字字符串:在內存中新建一份數據
          集合:修改內存中的同一份數據

 

3.對於集合,如何保留其修改前和修改后的數據?

 在內存中拷貝

4.對於集合,如何拷貝其n層元素同時拷貝?

深拷貝

 

 


1.對於 數字 和 字符串 而言,賦值、淺拷貝和深拷貝無意義,因為其永遠指向同一個內存地址。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
賦值,內存指向同一地址
>>> n1= 123
>>> n2=n1
>>> id(n1)
10109728
>>> id(n2)
10109728
>>>
>>> import  copy
>>> n3 = copy.copy(n1)
>>> id(n3)
10109728
>>> n4=copy.deepcopy(n1)
>>> id(n4)
10109728
>>>

 

 

2.對於字典、元祖、列表 而言,進行賦值、淺拷貝和深拷貝時,其內存地址的變化是不同的。

賦值,只是創建一個變量,該變量指向原來內存地址,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> import  copy
>>> n1 =  { 'k1' : 'v1' , 'k2' : 'v2' , 'k3' :[ 'liuyao' , 'job' ]}
>>> n1
{ 'k3' : [ 'liuyao' , 'job' ], 'k1' : 'v1' , 'k2' : 'v2' }
>>> n2 = n1
>>> id (n1)
140120750514696
>>> id (n2)
140120750514696
>>> id (n2[ 'k3' ])
140120750335688
>>> id (n1[ 'k3' ])
140120750335688
>>> id (n1[ 'k3' ][ 0 ])
140120778934064
>>> id (n2[ 'k3' ][ 0 ])
140120778934064
>>>

 

 

(3)淺拷貝,在內存中只額外創建第一層數據

1
2
3
4
5
6
7
8
9
10
11
12
>>> import  copy
>>> n1 =  { 'k1' : 'v1' , 'k2' : 'v2' , 'k3' :[ 'liuyao' , 'job' ]}
>>> n2 =  copy.copy(n1)
>>> id (n1)
140120750337544
>>> id (n2)
140120750371208
>>> id (n1[ 'k3' ][ 0 ])
140120778934064
>>> id (n2[ 'k3' ][ 0 ])
140120778934064
>>>

 

(4)深拷貝,在內存中將所有的數據重新創建一份(排除最后一層,即:python內部對字符串和數字的優化)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import  copy
>>> n1 =  { 'k1' : 'v1' , 'k2' : 'v2' , 'k3' :[ 'liuyao' , 'job' ]}
>>> n2 =  copy.deepcopy(n1)
>>> id (n1)
140120750514696
>>> id (n2)
140120750514888
>>> id (n1[ 'k3' ])
140120750335688
>>> id (n2[ 'k3' ])
140120750335752
>>> id (n2[ 'k3' ][ 0 ])
140120778934064
>>> id (n1[ 'k3' ][ 0 ])
140120778934064
>>>

 

 

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#深淺copy案例:監控模板
dic = {
     "cpu" :[ 80 ,],
     "mem" :[ 70 ,],
     "disk" :[ 90 ,],
 
}
print(dic)
a1=copy.copy(dic)
#淺copy會使所有的模板cpu都發生變化
a1[ 'cpu' ][ 0 ]= 20
print(a1)
print(dic)
#為了防止新模板修改導致舊模板被修改所以使用深copy
a2=copy.deepcopy(dic)
a2[ 'cpu' ][ 0 ]= 20
print(a2)
print(dic)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM