python中可變與不可變類型變量中一些較難理解的地方

  •  當函數內部引用一個全局變量時,若是此全局變量爲可變類型,那麼函數內部是能夠改變此全局變量的值,用不用globale申明全局變量都同樣。可是若是想給此變量從新賦值則必需要使用global。
l = []
d = {} def add_value(): d['frank'] = 'yangcaho' l.append(d) add_value() print(l) print(d) 輸出: [{'frank': 'yangcaho'}] {'frank': 'yangcaho'}
l = []
d = {} def add_value(): global l global d d['frank'] = 'yangcaho' l.append(d) add_value() print(l) print(d) 輸出: [{'frank': 'yangcaho'}] {'frank': 'yangcaho'}

 

  •   當函數內部引用一個全局變量時,若是此全局變量爲不可變類型,那麼若是要可以在函數內部改變全局變量的值,就須要用global,不用改變則不須要用global也能夠引用
a = 'frank'
def add_value():
    global a a = 'yangchao' add_value() print(a) yangchao

 

a = 'frank'
def add_value():
    b = a + 'yangchao'
    print(b) add_value() print(a) frankyangchao frank

   結論:可使用定義在函數外的全局變量的值(假設在函數內沒有同名的變量)。但強烈建議儘可能避免這樣作,由於這使得程序的讀者會不清楚這個變量是在哪裏定義的。使用global語句能夠清楚地代表變量是在外面的塊定義的。app

一些細微區別

可變對象如list的.paaend()操做與‘+’操做,的一些不一樣點。函數

  • 用 ‘+’ 其實是從新定義一個變量了。可是原列表的內存位置不會變,會開闢一個新的內存,L不是直接在原來l的基礎上增長而後指向l
l = ['frank', 'liuilu']
print(id(l))
L  = l + ['yangchao']
print(id(L))
print(l)
print(id(l))

36364616
36365960
['frank', 'liuilu']
36364616

 

  • 用 append 和 ’ += ‘其實是在原來變量基礎上增長。
l = ['frank', 'liuilu']
print(id(l))
l += ['yangchao']
print(l)
print(id(l))

43639112
['frank', 'liuilu', 'yangchao']
43639112
  •  一下代碼中個很坑的地方:爲何l的值不是[{'age': 1}, {'age': 2}]而是[{'age': 2}, {'age': 2}],由於l中存入的值是d實際是存入了d所指向內存地址。在第二次改變d的值得時候,就是改變了d的指向。因而第一次添加的d的值也會改變。
l = []
d = {} def add_value(): for i in range(1, 3): print('第%s次循環' %i) d['age'] = i print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value()  輸出結果 第1次循環 {'age': 1} ########## [] ########## [{'age': 1}] 第2次循環 {'age': 2} ########## [{'age': 2}] ########## [{'age': 2}, {'age': 2}]

   可是函數內若是是用賦值的方式(以下面兩種模式),那麼函數中的d就再也不是全局變量中的d了。因此有了每次賦值操做(即’=‘),每次append的d都是新的值。不會改變原來的值。ui

l = []
d = {} def add_value(): for i in range(1, 3): print('第%s次循環' %i) d = {'age', i} print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value() 第1次循環 {1, 'age'} ########## [] ########## [{1, 'age'}] 第2次循環 {2, 'age'} ########## [{1, 'age'}] ########## [{1, 'age'}, {2, 'age'}]

 

l = []
def add_value(): for i in range(1, 3): d = {} print('第%s次循環' %i) d['age'] = i print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value() 第1次循環 {'age': 1} ########## [] ########## [{'age': 1}] 第2次循環 {'age': 2} ########## [{'age': 1}] ########## [{'age': 1}, {'age': 2}]

   總得來說就是在操做可變對象的時候,只要有 = 就會從新開闢內存建立新變量,諸如list.append() 、list += 、list.pop、dic.update()、dict['key'] = value、實際上都是在原來變量的基礎上做修改,若是後面再次引用則會引用每次修改後的值。

  

a = []
b = [] c = {} d = {} e = 'frank' f = 'frank' print(id(a), id(b), id(c), id(d), id(e), id(f))

43770760 43770824 31284896 31284968 31302408 31302408

   可見每次建立一個空的可變對象時,都會從新開闢內存,但不可變對象就是指向原來的的地址空間。spa

相關文章
相關標籤/搜索