USF MSDS501 計算數據科學中文講義 2.5 數據別名

來源: ApacheCN『USF MSDS501 計算數據科學中文講義』翻譯項目

原文:Data Aliasingpython

譯者:飛龍git

協議:CC BY-NC-SA 4.0程序員

編程最棘手的事情之一是確切地肯定變量所指的數據。 請記住,咱們使用datasalary這樣的名稱來表示保存數據值的內存單元。 名稱比物理內存地址更容易記住,但咱們可能被愚弄。 例如,顯然兩個變量xy均可以具備相同的整數值 7:github

x = y = 7
print(x,y)

# 7 7

可是,你知道他們都指的是同一個 7 對象嗎? 換句話說,Python 中的變量始終是引用或指向數據的指針,所以變量在技術上並非持有值。 指針就像電話號碼「指向」手機,但指針自己不是手機自己。apache

咱們可使用內置的id(x)函數來發現這個間接的祕密層次,該函數返回由x指向的物理內存地址。 爲了證實這一點,讓咱們問一下xy指向的是什麼:編程

x = y = 7
print(id(x))
print(id(y))

'''
4468307488
4468307488
'''

哇! 他們是同樣的。 該數字表示 Python 存儲共享對象 7 的內存位置。數組

固然,做爲程序員,咱們並不認爲這些原子元素指的是同一個對象;請記住他們這樣作。 咱們更有可能將它們視爲相同數字的副本,由於lolviz在視覺上顯示:數據結構

from lolviz import *
callviz(varnames=['x','y'])

svg

讓咱們驗證字符串是否發生了一樣的事情:svg

name = 'parrt'
userid = name # userid now points at the same memory as name
print(id(name))
print(id(userid))

'''
4506178760
4506178760
'''

好的,很好,因此咱們實際上共享相同的內存地址來保存字符串'parrt',而且兩個變量名都指向同一個共享空間。咱們在語言實現中稱之爲別名函數

當咱們開始更改共享數據時,事情纔會變得怪異。整數和字符串不會發生這種狀況,由於它們是不可變的(沒法更改)。讓咱們看一個列表的兩個相同副本:

you = [1,3,5]
me  = [1,3,5]
print(id(you))
print(id(me))
callviz(varnames=['you','me'])

'''
4508962504
4508962440
'''

svg

這些列表具備相同的值,但存在不一樣的內存地址。他們不是別名;它們不是共享的。所以,更改一個不會改變另外一個:

you = [1,3,5]
me  = [1,3,5]
print(you, me)
you[0] = 99
print(you, me)

'''
[1, 3, 5] [1, 3, 5]
[99, 3, 5] [1, 3, 5]
'''

另外一方面,讓咱們看看若是咱們讓youme共享相同的列表副本(指向相同的內存位置)會發生什麼:

you = [1,3,5]
me  = you
print(id(you))
print(id(me))
print(you, me)
callviz(varnames=['you','me'])

'''
4509139464
4509139464
[1, 3, 5] [1, 3, 5]
'''

svg

如今,更改一個彷佛改變另外一個,但實際上二者都恰好引用內存中的相同位置:

you[0] = 99
print(you, me)
callviz(varnames=['you','me'])

# [99, 3, 5] [99, 3, 5]

svg

不要混淆「更改列表元素」和「更改指向列表的指針」:

you = [1,3,5]
me  = you
callviz(varnames=['you','me'])

svg

me = [9,7,5] # doesn't affect `you` at all
print(you)
print(me)
callviz(varnames=['you','me'])

'''
[1, 3, 5]
[9, 7, 5]
'''

svg

當咱們將列表或其餘數據結構傳遞給函數時,這種數據別名大量存在。 將Quantity列表傳遞給其參數名爲data的函數,意味着這兩個是別名。 咱們將在使用函數組織代碼的「符號可見性」部分中,更詳細地查看這個現象。

淺複製

X = [[1,2],[3,4]]
Y = X.copy() # shallow copy
callviz(varnames=['X','Y'])

svg

X[0][1] = 99
callviz(varnames=['X','Y'])
print(Y)

# [[1, 99], [3, 4]]
相關文章
相關標籤/搜索