python基礎學習(十二)變數進階
阿新 • • 發佈:2018-11-07
目錄
1. 變數的引用
- 變數 和 資料 都是儲存在 記憶體 中的
- 在
Python
中 函式 的 引數傳遞 以及 返回值 都是靠 引用 傳遞的
1.1 引用的概念
在 Python
中
- 變數 和 資料 是分開儲存的
- 資料 儲存在記憶體中的一個位置
- 變數 中儲存著資料在記憶體中的地址
- 變數 中 記錄資料的地址,就叫做 引用
- 使用
id()
函式可以檢視變數中儲存資料所在的 記憶體地址
注意:如果變數已經被定義,當給一個變數賦值的時候,本質上是 修改了資料的引用
- 變數 不再 對之前的資料引用
- 變數 改為 對新賦值的資料引用
1.2 變數引用 的例項
在
ipython3
中,定義兩個變數a
、b
,並使用id()
函式檢視其記憶體地址。
如下圖,標示出了變數和資料的應用關係:
編寫程式碼來說明
a = 1 print("a的記憶體地址是:%d" % id(a)) b = 2 print("b的記憶體地址是:%d" % id(b)) c = 2 print("c的記憶體地址是:%d" % id(c))
1.3 函式的引數和返回值的傳遞
在 Python
中,函式的 實參/返回值 都是是靠 引用 來傳遞來的,寫了小的例子嘗試下:
def test(num): print("-" * 50) print("%d 在函式中的記憶體地址是 %d" % (num, id(num))) result = 12 print("返回值 %d 在記憶體中的地址是 %d" % (result, id(result))) print("-" * 50) return result n = 100 print("%d在呼叫之前的記憶體地址是%d" % (n, id(n))) r = test(n) print("呼叫函式後,實參 %d 的記憶體地址是 %d" % (n, id(n))) print("呼叫函式後,返回值 %d 的記憶體地址是 %d" % (r, id(r)))
2. 可變和不可變型別
- 不可變型別,記憶體中的資料不允許被修改:
- 數字型別
int
,bool
,float
,complex
,long(2.x)
- 字串
str
- 元組
tuple
- 數字型別
- 可變型別,記憶體中的資料可以被修改:
- 列表
list
- 字典
dict
- 列表
注意
- 可變型別的資料變化,是通過 方法 來實現的
- 如果給一個可變型別的變數,賦值了一個新的資料,引用會修改
- 變數 不再 對之前的資料引用
- 變數 改為 對新賦值的資料引用
雜湊 (hash)
Python
中內建有一個名字叫做hash(o)
的函式- 接收一個 不可變型別 的資料作為 引數
- 返回 結果是一個 整數
雜湊
是一種 演算法,其作用就是提取資料的 特徵碼(指紋)- 相同的內容 得到 相同的結果
- 不同的內容 得到 不同的結果
- 在
Python
中,設定字典的 鍵值對 時,會首先對key
進行hash
已決定如何在記憶體中儲存字典的資料,以方便 後續 對字典的操作:增、刪、改、查- 鍵值對的
key
必須是不可變型別資料 - 鍵值對的
value
可以是任意型別的資料
- 鍵值對的
例子:
3. 區域性變數和全域性變數
- 區域性變數 是在 函式內部 定義的變數,只能在函式內部使用
- 全域性變數 是在 函式外部定義 的變數(沒有定義在某一個函式內),所有函式 內部 都可以使用這個變數
提示:在其他的開發語言中,大多 不推薦使用全域性變數 —— 可變範圍太大,導致程式不好維護!
3.1 區域性變數
- 區域性變數 是在 函式內部 定義的變數,只能在函式內部使用
- 函式執行結束後,函式內部的區域性變數,會被系統回收
- 不同的函式,可以定義相同的名字的區域性變數,但是 彼此之間 不會產生影響
區域性變數的作用
- 在函式內部使用,臨時 儲存 函式內部需要使用的資料
def test1():
num = 1
print(num)
num = 22
print("修改過後 %d" % num)
def test2():
num = 30
print(num)
test1()
test2()
print("結束")
區域性變數的生命週期
- 所謂 生命週期 就是變數從 被建立 到 被系統回收 的過程
- 區域性變數 在 函式執行時 才會被建立
- 函式執行結束後 區域性變數 被系統回收
- 區域性變數在生命週期 內,可以用來儲存 函式內部臨時使用到的資料
3.2 全域性變數
- 全域性變數 是在 函式外部定義 的變數,所有函式內部都可以使用這個變數
num = 10
def test1():
print(num)
def test2():
num = 22
print(num)
test1()
test2()
print(num)
注意:函式執行時,需要處理變數時 會:
- 首先 查詢 函式內部 是否存在 指定名稱 的區域性變數,如果有,直接使用
- 如果沒有,查詢 函式外部 是否存在 指定名稱 的全域性變數,如果有,直接使用
- 如果還沒有,程式報錯!
1) 在函式中不能直接修改 全域性變數的引用
- 全域性變數 是在 函式外部定義 的變數(沒有定義在某一個函式內),所有函式 內部 都可以使用這個變數
提示:在其他的開發語言中,大多 不推薦使用全域性變數 —— 可變範圍太大,導致程式不好維護!
- 在函式內部,可以 通過全域性變數的引用獲取對應的資料
- 但是,不允許直接修改全域性變數的引用 —— 使用賦值語句修改全域性變數的值
num = 10
def test1():
print("test1" + "*" * 50)
num = 100
print(num)
def test2():
print("test2" + "*" * 50)
print(num)
test1()
test2()
print("over")
注意:只是在函式內部定義了一個區域性變數而已,只是變數名相同 —— 在函式內部不能直接修改全域性變數的值
2) 在函式內部修改全域性變數的值
- 如果在函式中需要修改全域性變數,需要使用
global
進行宣告
num = 10
def test1():
print("test1" + "*" * 50)
global num
num = 100
print(num)
def test2():
print("test2" + "*" * 50)
print(num)
test1()
test2()
print("over")
3) 全域性變數定義的位置
- 為了保證所有的函式都能夠正確使用到全域性變數,應該 將全域性變數定義在其他函式的上方
a = 1
def test():
print(a)
print(b)
print(c)
b = 2
test()
c = 3
注意
- 由於全域性變數 c,是在呼叫函式之後,才定義的,在執行函式時,變數還沒有定義,所以程式會報錯!
4) 全域性變數命名的建議
- 為了避免區域性變數和全域性變量出現混淆,在定義全域性變數時,有些公司會有一些開發要求,例如:
- 全域性變數名前應該增加
g_
或者gl_
的字首
提示:具體的要求格式,各公司要求可能會有些差異
gl_num = 33
gl_name = "zfx"
def test():
num = 10
print(num)
print(gl_name)
test()