代碼塊、快取機制、深淺拷貝、集合
- id、is、==
- id: 可類比為身份號,具有唯一性,若id 相同則為同一個資料,
#獲取資料的記憶體地址(隨機的地址:記憶體臨時加載,存盤資料,當程式運行結束后,記憶體地址即被丟棄):
i = 'a'
print(id(i))
>>>2047746570672
print(id(i))
>>>2020558633392
print(id(i))
print(id(i))
>>>1908036008368
1908036008368
l1 = [1,2,3]
l2 = [1,2,3]
print(l1 == l2)
>>>True #比較的是兩邊的值是否相等,
- is 判斷id是否相同 (‘’==’‘判斷值是否相同)
l1 = [1,2,3]
l2 = [1,2,3]
print(l1 is l2)
>>>False #判斷的是記憶體地址是否相同,
print(id(l1))
print(id(l2))
>>>2648963830216
2648963830728
l1 = [1,2,3]
l2 = l1
print(l1 is l2)
print(id(l1))
print(id(l2))
>>>True
2053863395784
2053863395784
s1 = 'iam'
s2 = 'iam'
print(s1 is s2)
>>>True
print(id(s1))
print(id(s2))
>>>2188534085552
2188534085552
? id相同,值一定相同,值相同,id不一定相同,
-
代碼塊:python的程式是由代碼塊構造的,塊是一個python程式的腳本,它是作為一個單元執行的,一個模塊,一個函式,一個類,一個檔案等都是代碼塊,而作為互交命令方式輸入的每個命令都是一個代碼塊,兩個機制:如果在同一代碼塊下,則采用同一代碼塊下的換快取機制,如果是不同代碼塊,則采用小資料池的駐留機制,
-
-
同一個代碼塊的快取機制(字串駐留機制):機制內容:Python在執行同一個代碼塊的初始化物件的命令時,會檢查是否其值是否已經存在,如果存在,會將其重用,換句話說:執行同一個代碼塊時,遇到初始化物件的命令時,他會將初始化的這個變數與值存盤在一個字典中,在遇到新的變數時,會先在字典中查詢記錄,如果有同樣的記錄那么它會重復使用這個字典中的之前的這個值,即:id相同,
適用物件: int(float)::任何數字在同一代碼塊下都會復用,
str:幾乎所有的字串都會符合快取機制(1,非乘法得到的字串都滿足代碼塊的快取機制,,乘法得到的字串分兩種情況:1. 乘數為1時,任何字串滿足代碼塊的快取機制,2. 乘數>=2時,僅含大小寫字母,數字,下劃線,總長度<=20,滿足代碼塊的快取機制)
s1 = 'iam'*1 s2 = 'iam'*1 print(s1 is s2) >>>Truebool:True和False在字典中會以1,0方式存在,并且復用,
優點:能夠提高一些字串,整數處理人物在時間和空間上的性能;需要值相同的字串,整數的時候,直接從‘字典’中取出復用,避免頻繁的創建和銷毀,提升效率,節約記憶體,
-
在不同一個代碼塊內的快取機制:小資料池,也稱為小整數快取機制,或者稱為駐留機制等等,Python自動將-5~256的整數進行了快取,當你將這些整數賦值給變數時,并不會重新創建物件,而是使用已經創建好的快取物件,
python會將一定規則的字串在字串駐留池中,創建一份,當你將這些字串賦值給變數時,并不會重新創建物件, 而是使用在字串駐留池中創建好的物件,
其實,無論是快取還是字串駐留池,都是python做的一個優化,就是將~5-256的整數,和一定規則的字串,放在一個‘池’(容器,或者字典)中,無論程式中那些變數指向這些范圍內的整數或者字串,那么他直接在這個‘池’中參考,言外之意,就是記憶體中之創建一個,
適用物件: int(float):那么大家都知道對于整數來說,小資料池的范圍是-5~256 ,如果多個變數都是指向同一個(在這個范圍內的)數字,他們在記憶體中指向的都是一個記憶體地址,
# pycharm 通過運行檔案的方式執行下列代碼: 這是在同一個檔案下也就是同一代碼塊下,采用同一代碼塊下的快取機制, i1 = 1000 i2 = 1000 print(i1 is i2) # 結果為True 因為代碼塊下的快取機制適用于所有數字 >>>True #通過互動方式中執行下面代碼,這是不同代碼塊下,則采用小資料池的駐留機制, >>> i1 = 1000 >>> i2 = 1000 >>> print(i1 is i2) False # 不同代碼塊下的小資料池駐留機制 數字的范圍只是-5~256.str:1.字串的長度為0或者1,默認都采用了駐留機制(小資料池),2.字串的長度>1,且只含有大小寫字母,數字,下劃線時,才會默認駐留,3.用乘法得到的字串,分兩種情況:1 乘數為1,滿足規則的字串,默認駐留,2. 乘數>=2時:僅含大小寫字母,數字,下劃線,總長度<=20,默認駐留,
#4.指定駐留 from sys import intern a = intern('hello!@'*20) b = intern('hello!@'*20) print(a is b) >>>True #指定駐留是你可以指定任意的字串加入到小資料池中,讓其只在記憶體中創建一個物件,多個變數都是指向這一個字bool值就是True,False,無論你創建多少個變數指向True,False,那么他在記憶體中只存在一個,
# 雖然在同一個檔案中,但是函式本身就是代碼塊,所以這是在兩個不同的代碼塊下,不滿足小資料池(駐存機制),則指向兩個不同的地址, def func(): i1 = 1000 print(id(i1)) # 2288555806672 def func2(): i1 = 1000 print(id(i1)) # 2288557317392 func() func2()優點:能夠提高一些字串,整數處理人物在時間和空間上的性能;需要值相同的字串,整數的時候,直接從‘池’里拿來用,避免頻繁的創建和銷毀,提升效率,節約記憶體
-
參考文章:https://www.cnblogs.com/jin-xin/articles/9439483.html
-
集合 (set):容器型資料型別,要求它里面的元素是不可變的資料(可哈希),但它本身是可變的資料型別(不可哈希),集合是無序的,以{}存放資料,
-
作用:串列的去重;關系的測驗(交集,并集…)
/1. 集合的創建:
set = {1,2,'a'} #空集合的表示: set1 = set() #set1 = {}表示空字典/2 . 增:add update()#迭代增加,有重復的則去重
set1 = {1,2} set1.add('a') print(set1) >>>{'a', 1, 2} #集合無序 set1.update('asdfdsa') print(set1) >>>{'a', 1, 2, 'f', 's', 'd'}/3. 刪:remove()(按照元素洗掉,pop()隨機洗掉,clear()清空集合 del 洗掉集合
set1 = {'a', 1, 2, 'f', 's', 'd'} set1.remove('a') print(set1) >>>{1, 2, 's', 'f', 'd'} set1.pop() print(set1) >>>{2, 's', 'f', 'd'} set1.clear() print(set1) >>>{} del set1/4. 改:先洗掉再增加
-
交、并、
/1 . 交集,(&或者intersection) 集合共同有的元素
set1 = {1,2,3} set2 = {2,3,4} print(set1 & set2) #or print(set1.intersection) >>>{2,3}/2. 并集,(|或者union)集合所有的元素
set1 = {1,2} set2 = {2,3} print(set1 | set2) #or print(set1.union(set2)) >>>{1,2,3}/3. 差集 ( - 或者difference) ,前一集合獨有的元素
set1 = {1,2,3,4,5} set2 = {2,4,6} print(set1 - set2) #or print(set1.difference(set2)) >>>{1,3,5}/4 . 反交集,(^ 或者symmetric_difference)每個集合獨有的元素
set1 = {1,2,3,4,5} set2 = {3,4,5,6,7} print(set1 ^ set2) #or print(set1.symmetric_difference(set2)) >>>{1,2,6,7}/5. 子集與超集
set1 = {1,2} set2 = {1,2,3} print(set1 < set2) >>>True print(set1.issubset(set2)) #set1是set2的子集 >>>True print(set2 > set1) >>>True print(set2.issuperset(set1)) #set2是set1的超集 >>>True/6. frozenset()讓集合變為不可變型別
s = frozenset('qweasd') print(s,type(s)) >>>frozenset({'q', 'e', 'w', 's', 'a', 'd'}) <class 'frozenset'>
-
-
深淺copy
-
淺copy:在記憶體中開辟一個新的空間存放copy的物件(串列、字典),但是里面的所有元素與被copy物件的里面的元素共用一個,
l1 = [1,2] l2 = l1 l1.append(3) print(l2) >>>[1,2,3] #l1,l2兩變數指向同一個id(資料) #淺copy l3 = [1,2,['a']] l4 = l3.copy() l3.append(3) print(l3) >>>[1,2,['a'],3] print(l4) >>>[1,2,['a']] l3[-2].append(4) #or l4[-1].append(4) print(l3) >>>[1, 2, ['a', 4], 3] print(l4) >>>[1,2,['a',4]] #l4與l3串列中的資料id是相同的,但l4與l3串列id不相同,即l3中的每個元素與l4中的每個元素使用的是相同的一個id,但l4與l3用的不是同一個id,其實串列第一個一個的槽位,它儲存的是物件的記憶體地址,淺拷貝仍然使用原來的物件的記憶體地址,對儲存的可變物件可以進行更改;若改變不可變型別,則改變的不是不可變型別本身,而是變數的指向關系
-
-
深copy,需匯入模塊copy(淺copy也可以匯入copy模塊),不可變的資料型別沿用之前的記憶體地址,可變的資料型別創建新的記憶體地址,
import copy l3 = [1,2,['a']] l4 = copy.deepcopy(l3) #淺copy為 l4 = copy.copy(l3) l3[-1].append(3) print(l3) >>>[1,2,['a',3]] print(l4) >>>[1,2,['a']] #淺copy輸出為 [1,2,['a',3]] #串列第一個一個的槽位,它儲存的是物件的記憶體地址,深拷貝會創建一個新的物件的記憶體地址,python對深copy做了一個優化,將物件為不可變資料型別的記憶體地址沿用同一個,只重新再創建一份可變資料型別的記憶體地址,
淺copy:(list,dict),嵌套的不可變的資料型別是同一個id,可變型別也是同一個id,
深copy:(list,dict),嵌套的不可變的資料型別是同一個id,嵌套的可變的資料型別不是同一個id,
l1 = [1,2,['a']]
l2 = l1[:]
l1[-1].append(3)
print(l2)
>>>[1,2,['a',3]] #切片是淺copy
import copy
l1 = [1,2,[3,4]]
l2 = copy.copy(l1)
l3 = copy.deepcopy(l1)
print(l1[0] is l2[0])
>>>True
print(l2[0] is l3[0])
>>>True
print(l3[0] is l1[0])
>>>True
print(l1[2] is l2[2])
>>>False
print(l1 is l2)
>>>False
print(l3 is l1)
>>>False
#無論是淺copy還是深copy,都會創建一個新的資料型別,但是資料型別中的不可變資料型別都是同一個(id相同),深copy的可變資料型別不是同一個(id不同),
補充內置函式:
l1 = ['a','b','c']
for i in enumerate(l1,start=50): #start可默認不寫
print(i)
>>>(50, 'a')
(51, 'b')
(52, 'c')
#小題試做,看代碼寫結果:
#1:
l1 = [1,2,3,[4,5]]
l2 = [1,2,3,[4,5]]
a = l1 == l2 #先看等號右邊
b = l1 is l2
print(a) #True
print(b) #False
#2.
data_list = []
for i in range(10):
data = https://www.cnblogs.com/wby-110/p/{}
data['age'] = i
data_list.append(data)
print(data)
>>>{'age': 9}
print(data_list)
>>>[{'age': 0}, {'age': 1}, {'age': 2}, {'age': 3}, {'age': 4}, {'age': 5}, {'age': 6}, {'age': 7}, {'age': 8}, {'age': 9}]
#對比:
data_list = []
data = https://www.cnblogs.com/wby-110/p/{}
for i in range(10):
data['age'] = i
data_list.append(data)
print(data_list)
>>>[{'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}]
import copy
l1 = [1,2,{'name':'山就在那兒','number':[3,4,5]},6,7]
l2 = copy.deepcopy(l1)
print(l1[2] is l2[2]) #False
print(l1[2]['name'] is l2[2]['name']) #True #同一代碼塊下的快取機制,只適用于不可變物件
print(l1[2]['number'] is l2[2]['number']) #False
l1[2]['name']='a'
print(l1[2])
{'name': 'a', 'number': [3, 4, 5]}
print(l2[2])
{'name': '山就在那兒', 'number': [3, 4, 5]}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/175711.html
標籤:Python
下一篇:Python——專案-小游戲
