菜鳥學Python(3):引用和引用引數
阿新 • • 發佈:2019-01-06
在Python.cn的郵件列表中看到有人問了一個問題:
>>> a=[]
>>> b={'num':0,'sqrt':0}
>>> resurse=[1,2,3]
>>>for i in resurse:
b['num']=i
b['sqrt']=i*i
a.append(b)
>>> a
[{'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}]
a為什麼不是想象中的[{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9}]呢?
開始也沒有看明白,有人回覆說是引用的原因。所以就寫一些程式碼試一試:
>>> a=[]
>>> b={'num':0,'sqrt':0}
>>> b['num']=1
>>> b['sqrt']=1
>>> b
{'num': 1, 'sqrt': 1}
>>> a.append(b)
>>> a
[{'num': 1, 'sqrt': 1}]
>>> b['num']=2
>>> b['sqrt']=4
>>> b
{'num': 2, 'sqrt': 4}
>>> a.append(b)
>>> a
[{'num': 2, 'sqrt': 4}, {'num': 2, 'sqrt': 4}]
>>> id(a)
13346496
>>> id(a[0])
13335984
>>> id(a[1])
13335984
>>> id(b)
13335984
>>> a[0]['num']=4
>>> a
[{'num': 4, 'sqrt' : 4}, {'num': 4, 'sqrt': 4}]
>>> b
{'num': 4, 'sqrt': 4}
可以明顯的看出a中的元素其實就是b的引用!
開始抄書:)(Python程式設計金典P92)
和其他語言不一樣,傳遞引數的時候,python不允許程式設計師選擇採用傳值還是傳引用。Python引數傳遞採用的肯定是“傳物件引用”的方式。實際上,這種方式相當於傳值和傳引用的一種綜合。如果函式收到的是一個可變物件(比如字典或者列表)的引用,就能修改物件的原始值--相當於通過“傳引用”來傳遞物件。如果函式收到的是一個不可變物件(比如數字、字元或者元組)的引用,就不能直接修改原始物件--相當於通過“傳值'來傳遞物件。
說了半天,上面那個程式應該怎麼處理才能實現想要的效果類?
>>> a=[]
>>> resurse=[1,2,3]
>>>for i in resurse:
b={'num':0,'sqrt':0}
print id(b)
b['num']=i
b['sqrt']=i*i
a.append(b)
13334544
13335120
13335840
>>> a
[{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9}] 這樣就可以了。相當於每次都新建一個字典物件。但有些不好,如果i的值很大,就會佔很多不必要的記憶體。
不如這樣:
>>> a = []
>>>for i in (1, 2, 3, 4, 5, 6, 7):
a.append({"num": i, "sqrt": i * i})
>>> a
[{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9},
{'num': 4, 'sqrt': 16},{'num': 5, 'sqrt': 25}, {'num': 6, 'sqrt': 36},
{'num': 7, 'sqrt': 49}]
>>> a=[]
>>> b={'num':0,'sqrt':0}
>>> resurse=[1,2,3]
>>>for i in resurse:
b['num']=i
b['sqrt']=i*i
a.append(b)
>>> a
[{'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}]
a為什麼不是想象中的[{'num': 1, 'sqrt': 1}, {'num':
開始也沒有看明白,有人回覆說是引用的原因。所以就寫一些程式碼試一試:
>>> a=[]
>>> b={'num':0,'sqrt':0}
>>> b['num']=1
>>> b['sqrt']=1
>>> b
{'num': 1, 'sqrt': 1}
>>> a.append(b)
>>> a
[{'num': 1, 'sqrt': 1}]
>>> b['num']=2
>>>
>>> b
{'num': 2, 'sqrt': 4}
>>> a.append(b)
>>> a
[{'num': 2, 'sqrt': 4}, {'num': 2, 'sqrt': 4}]
>>> id(a)
13346496
>>> id(a[0])
13335984
>>> id(a[1])
13335984
>>> id(b)
13335984
>>> a[0]['num']=4
>>> a
[{'num': 4, 'sqrt'
>>> b
{'num': 4, 'sqrt': 4}
可以明顯的看出a中的元素其實就是b的引用!
開始抄書:)(Python程式設計金典P92)
和其他語言不一樣,傳遞引數的時候,python不允許程式設計師選擇採用傳值還是傳引用。Python引數傳遞採用的肯定是“傳物件引用”的方式。實際上,這種方式相當於傳值和傳引用的一種綜合。如果函式收到的是一個可變物件(比如字典或者列表)的引用,就能修改物件的原始值--相當於通過“傳引用”來傳遞物件。如果函式收到的是一個不可變物件(比如數字、字元或者元組)的引用,就不能直接修改原始物件--相當於通過“傳值'來傳遞物件。
說了半天,上面那個程式應該怎麼處理才能實現想要的效果類?
>>> a=[]
>>> resurse=[1,2,3]
>>>for i in resurse:
b={'num':0,'sqrt':0}
print id(b)
b['num']=i
b['sqrt']=i*i
a.append(b)
13334544
13335120
13335840
>>> a
[{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9}] 這樣就可以了。相當於每次都新建一個字典物件。但有些不好,如果i的值很大,就會佔很多不必要的記憶體。
不如這樣:
>>> a = []
>>>for i in (1, 2, 3, 4, 5, 6, 7):
a.append({"num": i, "sqrt": i * i})
>>> a
[{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9},
{'num': 4, 'sqrt': 16},{'num': 5, 'sqrt': 25}, {'num': 6, 'sqrt': 36},
{'num': 7, 'sqrt': 49}]