Assignment Statement 稱指派敘述,是幾乎任何一種程式語言都會出現的語句,是用來宣告或是給予變數具體的資料的。而「=」符號在多數程式語言中都是賦值運算子(Assignment Operators)。 例如: A = 1 ,不過實際上在Python語言中會讓變數A成為數值1的引用
在Python中當一個值(value)被建立之後,只要有變數被指派為它,變數就會用參考的方式指向該值,一旦該值不再被引用則會被回收。這裡舉個例子說明:
# show how varable(name) reference to a value (object) in python
# step 1
# ┌───┐
# │ │ x = 1
# │ x ├───┐
# │ │ │
# └───┘ ┌─▼─┐
# │ 1 │
# └─▲─┘
# ┌───┐ │
# │ │ │
# │ y ├───┘
# │ │ y = 1
# └───┘
x = 1
y = 1
print('x = 1')
print('y = 1')
print(f"x reference to {id(x)}")
print(f"y reference to {id(y)}")
print(f"1 reference to {id(1)}")
print('--------------------------')
# x,y,1 have same reference
#
#
# step 2
# ┌───┐
# │ │ x = 2
# │ x ├───────────┐
# │ │ │
# └───┘ ┌───┐ ┌─▼─┐
# │ 1 │ │ 2 │
# └───┘ └─▲─┘
# ┌───┐ │
# │ │ │
# │ y ├───────────┘
# │ │ y = 2
# └───┘
x = 2
y = 2
print('x = 2')
print('y = 2')
print(f"x reference to {id(x)}")
print(f"y reference to {id(y)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
print('--------------------------')
# x,y,2 have same new reference and 1 had the old reference
# step 3
# ┌───┐
# │ │
# │ x ├───┐
# │ │ │ ┌───┐
# └───┘ ┌─▼─┐ ┌───┐ │ │
# │ 2 │ │ 1 │◄────┤ z │
# └─▲─┘ └───┘ │ │
# ┌───┐ │ └───┘
# │ │ │
# │ y ├───┘
# │ │
# └───┘
z = 1
print('z = 1')
print(f"x reference to {id(x)}")
print(f"y reference to {id(y)}")
print(f"z reference to {id(z)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
# x,y,2 have same new reference and 1 , z had the old reference
為了說明需要,這裡使用Python的函數id(),它會返回物件的記憶體位址,這讓我們能觀察誤變數實際指向的位址。首先第一步, x = 1 以及 y = 1 分別讓變數x和y指向「1」這個數值,所以「x」、「y」和「1」三者指向的記憶體位址都相同(皆為數值1的位址)。第二步我們的指令 x = 2 以及 y = 2 ,實際上是新增加「2」這個數值,並讓變數x和y改為指向「2」,而原先的「1」由於還有被使用,所以保留著。這時候「x」、「y」和「2」三個的記憶體位址都相同(皆為數值2的位址),另外「1」的位置與第一步時相同。第三步,我們新增變數z,指令z = 1。這時會把z指向第一步驟時「1」的位置,所以最終結果「x」、「y」和「2」三個的記憶體位址都相同,而「z」和「1」這兩個記憶體位址相同,並與前組不同。
在前述的例子中,「1」和「2」都是不可變物件(Immutable objects),其值和記憶體位置一旦被設定就無法更改,反而是透過變數的重新指向來改變值所代表的意義。再舉另一個例子:
# show how varable(name) reference to a value (object) in python
# while changing value
x = 1
y = 1
# step 1
# ┌───┐
# │ │ x = 1
# │ x ├───┐
# │ │ │
# └───┘ ┌─▼─┐
# │ 1 │
# └─▲─┘
# ┌───┐ │
# │ │ │
# │ y ├───┘
# │ │ y = 1
# └───┘
print('x = 1')
print('y = 1')
print(f"x reference to {id(x)}")
print(f"y reference to {id(y)}")
print(f"1 reference to {id(1)}")
# step 2
# ┌───┐
# │ │
# │ x │
# │ ├───┐
# └───┘ ┌─▼─┐
# │ 2 │
# └───┘
# ┌───┐
# │ │ ┌───┐
# │ y ├─► 1 │
# │ │ └───┘
# └───┘
x = y + 1
print('x = y + 1')
print(f"x = {x}")
print(f"x reference to {id(x)}")
print(f"y reference to {id(y)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
在這個例子中,第一步先建立變數x和y,並同時賦予初始值=1,但其實是把它們都指向數值1的位址。第二步做了運算,x = y + 1 ,此時x的值被改成2,但實際上不是把數值1的位址的內容改寫,而是新增另一個記憶體位址並寫上數值2,然後把變數x指過去。而原先的數值1並沒有更動。
除了不可變物件之外,也有些是可變的物件(Mutable Objects),例如容器類的。這裡以list舉例:
# show how varable(name) reference to a value (object) in python
# while changing a list
x = [1,2]
print('x = [1,2]')
print("current x : ")
print(x)
print(f"x reference to {id(x)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
x.append(2)
print('x.append(2)')
print("current x : ")
print(x)
print(f"x reference to {id(x)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
x.append(3)
print('x.append(3)')
print("current x : ")
print(x)
print(f"x reference to {id(x)}")
print(f"1 reference to {id(1)}")
print(f"2 reference to {id(2)}")
print(f"3 reference to {id(3)}")
x 指向的記憶體位置是固定的,但內含的值有更動。
本文允許重製、散布、傳輸以及修改,但不得為商業目的之使用
使用時必須註明出處自:楊明翰 , 台灣人工智慧與資料科學研究室 https://aistudio.tw