Re: [問題] 關於賦值

作者: germun (ger)   2019-02-04 01:38:26
※ 引述《nevikw39 (牧)》之銘言:
: 如題,Python 的變數系統至今對我仍然是個謎。
:
: Python 既是動態語言,變數感覺傾向於強型別但又不需要再宣告。因此,直譯器到底是怎
: 麼判斷型別的?而且,同一個變數名稱前後可能指涉不同型別。
:
雖然python沒有指標, 但沒有指標觀念的話很容易落入陷阱
沒有指標或物件導向觀念的話最好先去懂
首先python沒有變數(variable), 只有`name`
(我不知怎麼翻, 所以以下全稱name)
用`賦名`形容比較合適, 只是我們有時還是習慣用變數來稱呼
所謂name的意思, 就是等號左邊只是個名稱, 將其名稱指到右邊的物件
所有物件的屬性定義全都是依右邊assign的物件來決定,
所以才不需事先宣告, 因為物件在建立時已有它的型態和各種資料
等號只是將 name 指到該物件, 或反過來說: 給右邊的物件取一個 name
例如:
==========
a = 2
b = 2
==========
若從C的角度來開, 是將a跟b的值設成2,
但從python來看, 任何數字或任何字串本身也都是物件
這邊是分別將 a 跟 b 指到 `2` 這個int物件
所以 id(a) == id(b) 跟 id(a) == id(2) 會是True, 因為都指到同一物件 `2`
接著再一行
===========
b = 4
===========
正確的解讀是將 b `重新指向` 4 這個物件
: 主要想請教的是 dict 和 list 的部分:
: # base 讀自 json
: def callback(e):
: ...
: data = base
從這一行來解讀
base是已存在的name, 已經有其指向的物件 (舉例來說是個字串"abc"好了)
那麼base其實只是個指向"abc"的 name
這行的結果就只會是:
=> 新建一個name `data`, 指向`base`所指的物件
白話講就是, base指向誰, 那麼data也同樣指向誰
也就是:
base -> "abc"
data -> "abc"
兩者 "abc" 是同記憶體位置的同一物件
因而你透過 `data[...] = XXX` 去改動的元素內容, 對應的`base[...]`也會改動
但你若直接:
======
data = "ddd"
======
這時就會是將data重新指向一個新物件 "ddd", 而不會改動base的內容
: data[...] = ...
: 這樣好像會改動到原本 base 的值欸?
: 還有例如:
: lst = []
lst是個物件 `[]`
: a = [0, 0, 0]
a也是個物件 `[0, 0, 0]`
: lst.append(a)
把a放入lst
此時lst[0] 會指向 a 所指的物件
id(lst[0]) == id(a) 為 True
: for i in range(len(a)):
: a[i] += 1
a還是同一個list, 記憶體位置不變, 但裡面元素所指的物件都變成1
即 a[0], a[1], ... = 1, 1, ...
到這時你lst[0]裡面已經跟著變成 [1,1,1], 因為是同一個list
ps. 要注意這跟 `a = [1,1,1]` 是不同行為, 這是重新建新的list
: lst.append(a)
再一次把a放進去,
所以lst[0], lst[1]都是同一個list,
一改內容兩個就一起改了
: 結果 lst 的值不是 [[0, 0, 0], [1, 1, 1]] ,而是 [[1, 1, 1], [1, 1, 1]] 欸!
: 所以,當我作 data = base 這個運算時,感覺只是將 data 參考指向 base 這個實體而已
: ,而我若 lst.append(a) 也只是把 lst 的尾端指向 a。那麼,Python 的指派究竟何時是
: 參考,何時是複製呢?
你如果一定要用list的話, 那就一定要先建一個新list
例如 b = [], 再把值丟進去
或直接複製內容:
b = a[:]
這樣的解讀相當於:
b = [a[0], a[1], ....]
把a的元素分別取出重新建一個list, 如此a跟b就會是不同list
甚至是
a = a[:] # 重新建一個list `a`, 原本的list a遺失,
但這邊原本的 a 已經放入`lst`中所以無妨
但要注意這邊不會出錯是因為a[0]本身是指向int物件, 因此不會有問題
如果 a[0] 指向的是list這類物件, 也就是你的 a 若是二維以上的list,
或其他具有屬性的物件, 那又會回到上述狀況了
如果你要用到2維以上來計算值, 例如矩陣
那麼用numpy array是比較容易
不過numpy array跟list又有微妙不同之處, 那又是另一回事了
作者: XperiaZ6C (真●安卓輕旗艦)   2019-02-04 05:30:00
作者: yangs0618 (阿彰)   2019-02-04 12:25:00
那如果data指向base再把base改指向跟原本不同呢
作者: s06yji3 (阿南)   2019-02-04 16:42:00
data不變因為只是將base這個名字綁到其他物件而已
作者: utap2001 (尋找一個漫長的答案 )   2019-02-08 21:42:00
所以Python跟c,java的邏輯不同,是把等號左邊指向右邊

Links booklink

Contact Us: admin [ a t ] ucptt.com