首頁  >  問答  >  主體

[Python]list.append()在for循环中每次添加的都是最后的一个元素

迷茫迷茫2714 天前543

全部回覆(2)我來回復

  • 阿神

    阿神2017-04-17 16:41:44

    首先得知道三點。
    1、程式的運作是需要去記憶體申請地址的。
    2、賦值運算只是記憶體中某一塊位址的參考。
    3、Python 內建的 id()函數。 此函數從概念上可以理解為得到當前生命下的記憶體位址。

    id(object)
    Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime。

    CPython implementation detail: This is the address of the object in memory.

    由此我們可以得到以下結果:

    a = 1
    b = 1
    c = a
    d = b
    
    print(id(1))                                       # value x
    print(id(a))                                       # value x
    print(id(b))                                       # value x
    print(id(c))                                       # value x
    print(id(d))                                       # value x
    
    print(id(1) == id(a) == id(b) == id(c) == id(d))   # True

    在此基礎去看 字典/dict :

    當宣告一個字典 info = {} 的操作時候,該字典就已經在記憶體中取得了某塊位址。
    對該字典進行操作時,如 info['name'] = 'github' 的時候,這個字典依舊是之前所佔用的位址。
    可透過id 函數追蹤得到以下程式碼:

    info = {}                       
    print(id(info))                 # value y
    
    info['name'] = 'github'
    print(id(info))                 # value y

    因此,對於你改進前的程式碼
    pathlist.append(info)添加進去的始終是同一個info,準確的說,始終是同一塊位址,而這個info內容在不停的修改。
    參考以下程式碼:

    info = {'name': 'github'}
    pathlist = [info,]
    
    print(id(info))                 # value z
    print(id(pathlist[0]))          # value z

    然後,對於改進後的程式碼
    info = {} 的操作放在了循環內,結果就是每一次循環都申請使用一段新的地址,只不過依舊用info來引用。
    可由一下程式碼對比:

    info = {}
    print(id(info))                 # value m
    
    info = {}
    print(id(info))                 # value n

    兩次列印的值是不等的。

    另外
    第一段程式碼中的
    pathlist.append(info) #將dict加入list
    這個註釋, 了。

    希望能幫到你。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 16:41:44

    原始碼

    listDirectory最終回傳的是

    [info, info, info...]

    而info每次循環都會更新,但最終必為

    {'name': last_loop_item}

    所以會有那樣的結果

    更新程式碼

    更新後的程式碼就比較直觀了,
    每次info都是新生成的dict,append的是每次循環產生的結果

    回覆
    0
  • 取消回覆