日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

【Python学习】——语言风格(变量赋值、深浅拷贝、for循环陷阱)

發(fā)布時(shí)間:2023/12/10 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python学习】——语言风格(变量赋值、深浅拷贝、for循环陷阱) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

1、賦值

?2、賦值的分類——引用賦值、值賦值

1) 不可變對(duì)象引用賦值——字符串、數(shù)值、元組等

2)可變對(duì)象引用賦值——列表、集合、字典

3)可變與不可變對(duì)象的引用賦值內(nèi)部分析

4)在py文件中,和作用域有關(guān),如在同一個(gè)函數(shù)中的相同值的變量是相等的,即值相等,地址也相等

3、深拷貝與淺拷貝

4、循環(huán)——序列和非序列的循環(huán)中進(jìn)行元素的修改


?

1、賦值

# 賦值包含多種賦值方式,一般賦值、元組賦值、序列賦值、解包賦值 a = "long" b,c = "1",2 d,e,f,g = "long" h,*i = "long" print(a) print(b) print(c) print(d) print(e) print(f) print(g) print(h) print(i)

long
1
2
l
o
n
g
l
['o', 'n', 'g']

當(dāng)使用一個(gè)*前綴變量的時(shí)候,表示將序列對(duì)應(yīng)的元素全部收集到一個(gè)列表中(注意,總是一個(gè)列表),這個(gè)列表名為*開頭的那個(gè)變量名。*號(hào)可以出現(xiàn)在任意位置處,只要賦值的時(shí)候能前后對(duì)應(yīng)位置關(guān)系即可。

注意其中的幾個(gè)關(guān)鍵字:序列、對(duì)應(yīng)的元素、列表

  • 序列意味著可以是列表、元組、字符串等等
  • 列表意味著只要收集不報(bào)錯(cuò),賦值給解包變量的一定是一個(gè)列表
  • 對(duì)應(yīng)的元素意味著可能收集到0或任意個(gè)元素到列表。

不管如何,收集的結(jié)果總是列表,只不過可能是空列表或者只有一個(gè)元素的列表。

?

兩個(gè)注意事項(xiàng):

  • 因?yàn)樾蛄薪獍歉鶕?jù)元素位置來進(jìn)行賦值的,所以不能出現(xiàn)多個(gè)解包變量
  • 如果將序列直接賦值給單個(gè)解包變量時(shí)(即沒有普通變量),這個(gè)解包變量必須放在列表或元組中
  • a,*b,c,*d = L # 錯(cuò)誤 *a = L # 錯(cuò)誤 [*a] = L # 正確 (*a) = L # 正確

    ?2、賦值的分類——引用賦值、值賦值

    引用賦值——指的是將內(nèi)存地址賦值給變量來實(shí)現(xiàn)賦值

    1) 不可變對(duì)象引用賦值——字符串、數(shù)值、元組等

    a = 1000

    b = a

    a = 2000

    前兩行b=a是將1000的地址賦值給b,即a和b都是指向值1000的內(nèi)存地址。第三行a=2000是對(duì)a重新進(jìn)行賦值,因?yàn)閿?shù)值是不可改變的對(duì)象,因此會(huì)先開辟一個(gè)內(nèi)存地址用于存儲(chǔ)2000,然后將a指向2000

    不可變對(duì)象變量之間不會(huì)互相影響,即如果一開始兩個(gè)變量指向同一個(gè)內(nèi)存地址,當(dāng)其中一個(gè)變量的值發(fā)生了改變的時(shí)候,另一個(gè)變量不會(huì)受到影響

    對(duì)于不可變對(duì)象,修改變量的值意味著在內(nèi)存中要新創(chuàng)建一個(gè)數(shù)據(jù)對(duì)象

    a = 10000 b = a a = 20000>>> a,b (20000, 10000)

    2)可變對(duì)象引用賦值——列表、集合、字典

    對(duì)于可變對(duì)象,比如列表,它是在"原處修改"數(shù)據(jù)對(duì)象的(注意加了雙引號(hào))。比如修改列表中的某個(gè)元素,列表的地址不會(huì)變,還是原來的那個(gè)內(nèi)存對(duì)象,所以稱之為"原處修改"。例如:

    L1 = [111,222,333] L2 = L1 L1[1] = 2222>>> L1,L2 ([111, 2222, 333], [111, 2222, 333])

    L2是通過引用賦值得到的值,值為可變對(duì)象列表,當(dāng)對(duì)L1改變一個(gè)列表元素時(shí),其列表的地址不會(huì)發(fā)生改變,因此其L2的值也會(huì)發(fā)生相應(yīng)的改變

    在L1[1]賦值的前后,數(shù)據(jù)對(duì)象[111,222,333]的地址一直都沒有改變,但是這個(gè)列表的第二個(gè)元素的值已經(jīng)改變了。因?yàn)長1和L2都指向這個(gè)列表,所以L1修改第二個(gè)元素后,L2的值也相應(yīng)地到影響。也就是說,L1和L2仍然是同一個(gè)列表對(duì)象[111,2222,333]。

    結(jié)論是:對(duì)于可變對(duì)象,變量之間是相互影響的

    3)可變與不可變對(duì)象的引用賦值內(nèi)部分析

    可變對(duì)象和不可變對(duì)象的賦值形式雖然一樣,但是修改數(shù)據(jù)時(shí)的過程不一樣。

    對(duì)于不可變對(duì)象,修改數(shù)據(jù)是直接在堆內(nèi)存中新創(chuàng)建一個(gè)數(shù)據(jù)對(duì)象。如圖:

    對(duì)于可變對(duì)象,修改這個(gè)可變對(duì)象中的元素時(shí),這個(gè)可變對(duì)象的地址不會(huì)改變,所以是"原處修改"的。但需要注意的是,這個(gè)被修改的元素可能是不可變對(duì)象,可能是可變對(duì)象,如果被修改的元素是不可變對(duì)象,就會(huì)創(chuàng)建一個(gè)新數(shù)據(jù)對(duì)象,并引用這個(gè)新數(shù)據(jù)對(duì)象,而原始的那個(gè)元素將等待垃圾回收器回收。

    >>> L=[333,444,555] >>> id(L),id(L[1]) (56583832, 55771984) >>> L[1]=4444 >>> id(L),id(L[1]) (56583832, 55771952)

    如圖所示:

    4)在py文件中,和作用域有關(guān),如在同一個(gè)函數(shù)中的相同值的變量是相等的,即值相等,地址也相等

    3、深拷貝與淺拷貝

    1)深拷貝

    完全創(chuàng)建一個(gè)新的數(shù)據(jù)對(duì)象,不會(huì)受到其他變量的元素值變化的影響

    2)淺拷貝,只是拷貝了第一層的元素,若第一層的元素是可變對(duì)象,則引用的是可變對(duì)象的地址,因此還是會(huì)受到其他變量的影響

    # 引用賦值——只是得到了地址 print("賦值----------------------") L = [1,2,[3,4,5]] L2 = L print("修改元素前-----------") print(L) print(L2) print("修改元素后-----------") L[0] = 0 print(L) print(L2)

    賦值----------------------
    修改元素前-----------
    [1, 2, [3, 4, 5]]
    [1, 2, [3, 4, 5]]
    修改元素后-----------
    [0, 2, [3, 4, 5]]
    [0, 2, [3, 4, 5]]?

    print("淺拷貝------------------------")print("淺拷貝1------------------------") # 淺拷貝——只是拷貝了第一層的元素,若為不可變?cè)?#xff0c;則會(huì)重新為元素創(chuàng)建一個(gè)新的數(shù)據(jù)對(duì)象,若為可變數(shù)據(jù)對(duì)象,則只是拷貝了地址 L = [1,2,[3,4,5],6] L1 = L.copy() print("修改不可變對(duì)象的元素前-----------") print(L) print(L1) print("修改不可變對(duì)象的元素后-----------") L[0] = 0 print(L) print(L1)print("淺拷貝1------------------------") L = [1,2,[3,4,5],6] L1 = L.copy() print("修改可變對(duì)象的元素前-----------") print(L) print(L1) print("修改可變對(duì)象的元素后-----------") L[2][0] = 0 print(L) print(L1)print("淺拷貝2------------------------") L = [1,2,[3,4,5]] L3 = L[:] print("修改元素前-----------") print(L) print(L3) print("修改元素后-----------") L[0] = 0 L[2][0] = 0 print(L) print(L3)

    ?

    淺拷貝------------------------
    淺拷貝1------------------------
    修改不可變對(duì)象的元素前-----------
    [1, 2, [3, 4, 5], 6]
    [1, 2, [3, 4, 5], 6]
    修改不可變對(duì)象的元素后-----------
    [0, 2, [3, 4, 5], 6]
    [1, 2, [3, 4, 5], 6]
    淺拷貝1------------------------
    修改可變對(duì)象的元素前-----------
    [1, 2, [3, 4, 5], 6]
    [1, 2, [3, 4, 5], 6]
    修改可變對(duì)象的元素后-----------
    [1, 2, [0, 4, 5], 6]
    [1, 2, [0, 4, 5], 6]
    淺拷貝2------------------------
    修改元素前-----------
    [1, 2, [3, 4, 5]]
    [1, 2, [3, 4, 5]]
    修改元素后-----------
    [0, 2, [0, 4, 5]]
    [1, 2, [0, 4, 5]]

    from copy import deepcopy print("深拷貝------------------------") L = [1,2,[3,4,5]] L1 = deepcopy(L) L[0] = 0 L[2][0] = 0 print(L) print(L1)

    深拷貝------------------------
    [0, 2, [0, 4, 5]]
    [1, 2, [3, 4, 5]]

    一般我們使用到的都是淺拷貝

    4、循環(huán)——序列和非序列的循環(huán)中進(jìn)行元素的修改

    https://www.cnblogs.com/f-ck-need-u/p/10129317.html

    1)列表進(jìn)行原地修改時(shí)(L+=[val1,val2]),進(jìn)行后面的迭代時(shí),進(jìn)行迭代的是修改后的列表,因?yàn)閒or是一個(gè)迭代器,使用的是next,即通過索引進(jìn)行的,因此列表原地修改會(huì)導(dǎo)致元素出現(xiàn)奇怪的現(xiàn)象

    為了避免這種情況,我們對(duì)列表進(jìn)行修改時(shí),建議生成一個(gè)新的列表對(duì)象來進(jìn)行存放

    L = ['a','b','c','d','e']## 原處修改列表,新元素f、g也會(huì)被迭代 for i in L:if i in "de":L += ["f", "g"]print(i)## 創(chuàng)建新列表,新元素f、g不會(huì)被迭代 for i in L:if i in "de":L = L + ["f", "g"]print(i)

    這個(gè)for迭代器在迭代剛開始的時(shí)候,先找到L所指向的迭代對(duì)象,即內(nèi)存中的[1,2,3,4]。如果迭代過程中如果L變成了一個(gè)集合,或另一個(gè)列表對(duì)象,for的迭代并不會(huì)收到影響。但如果是在原處修改這個(gè)列表,那么迭代將會(huì)收到影響,例如新增元素也會(huì)被迭代到。

    這里通過列表索引來進(jìn)行元素的遍歷和修改即可避免上面的情況

    2)迭代一個(gè)列表,迭代過程中刪除一個(gè)列表元素。

    L = ['a','b','c','d','e'] for i in L:if i in "bc":L.remove(i)print(i)print(L)

    輸出的結(jié)果將是:

    b ['a', 'c', 'd', 'e']

    這個(gè)for循環(huán)的本意是想刪除b、c元素,但結(jié)果卻只刪除了b。通過結(jié)果可以發(fā)現(xiàn),c根本就沒有被for迭代。之所以會(huì)這樣,是因?yàn)榈絙的時(shí)候,滿足if條件,然后刪除了列表中的b元素。正因?yàn)閯h除操作,使得列表中b后面的元素整體前移一個(gè)位置,也就是c元素的索引位置變成了index=1,而index=1的元素已經(jīng)被for迭代過(即元素b),使得c幸運(yùn)地逃過了for的迭代。

    3)迭代的是字典或者集合時(shí),雖然兩者都是可變序列,但是時(shí)無序的,因此在迭代的過程中,是不允許字典或者集合發(fā)生改變的,否則會(huì)報(bào)錯(cuò)

    D = {'a':1,'b':2,'c':3,'d':4,'e':5}for i in D:if i in "bc":del D[i]print(i)print(D)

    報(bào)錯(cuò):

    b Traceback (most recent call last):File "g:/pycode/lists.py", line 12, in <module>for i in D: RuntimeError: dictionary changed size during iteration S = {'a','b','c','d','e'}for i in S:if i in "bc":S.remove(i)print(i)print(S)

    報(bào)錯(cuò):

    b Traceback (most recent call last):File "g:/pycode/lists.py", line 4, in <module>for i in L: RuntimeError: Set changed size during iteration

    若想修改字典的話,我們可以復(fù)制一份數(shù)據(jù)對(duì)象作為副本,然后將副本進(jìn)行迭代,將原來的字典或集合作為修改對(duì)象?

    D = {'a':1,'b':2,'c':3,'d':4,'e':5}for i in D.copy():if i in "bc":D.pop(i)print(i) print(D)S = {'a','b','c','d','e'}for i in S.copy():if i in "bc":S.remove(i)print(i) print(S)

    ?注意:在進(jìn)行可變對(duì)象數(shù)據(jù)對(duì)象的迭代與修改時(shí),我們只需要將迭代對(duì)象和修改對(duì)象分開就不會(huì)出現(xiàn)上述的錯(cuò)誤。

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的【Python学习】——语言风格(变量赋值、深浅拷贝、for循环陷阱)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。