1. 程式人生 > >python基礎學習(十二)變數進階

python基礎學習(十二)變數進階

目錄

1. 變數的引用

  • 變數 和 資料 都是儲存在 記憶體 中的
  • Python函式 的 引數傳遞 以及 返回值 都是靠 引用 傳遞的

1.1 引用的概念

Python

  • 變數資料 是分開儲存的
  • 資料 儲存在記憶體中的一個位置
  • 變數 中儲存著資料在記憶體中的地址
  • 變數記錄資料的地址,就叫做 引用
  • 使用 id() 函式可以檢視變數中儲存資料所在的 記憶體地址

注意:如果變數已經被定義,當給一個變數賦值的時候,本質上是 修改了資料的引用

  • 變數 不再 對之前的資料引用
  • 變數 改為 對新賦值的資料引用

1.2 變數引用 的例項

  • ipython3 中,定義兩個變數ab,並使用 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

注意

  1. 可變型別的資料變化,是通過 方法 來實現的
  2. 如果給一個可變型別的變數,賦值了一個新的資料,引用會修改
    • 變數 不再 對之前的資料引用
    • 變數 改為 對新賦值的資料引用

雜湊 (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. 首先 查詢 函式內部 是否存在 指定名稱 的區域性變數如果有,直接使用
  2. 如果沒有,查詢 函式外部 是否存在 指定名稱 的全域性變數如果有,直接使用
  3. 如果還沒有,程式報錯!

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()