1. 程式人生 > >2018-10-20學習python第七天

2018-10-20學習python第七天

  又有幾天沒有寫 python 筆記了,忙成狗


 1、變數進階(理解)

1.1  變數的引用

引用的概念

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

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

函式的引數和返回值的傳遞

  • 函式的 實參
    /返回值 都是是靠 引用 來傳遞來的

1.2  可變和不可變型別(特別注意)

記憶體資料不可變和記憶體資料可變

  • 不可變型別,記憶體中的資料不允許被修改:

    • 數字型別 intboolfloatcomplexlong(2.x)
    • 字串 str
    • 元組 tuple
  • 可變型別,記憶體中的資料可以被修改:

    • 列表 list
    • 字典 dict

舉一個例子

demo_list = [1, 2, 3]
print("定義列表後的記憶體地址 %d" % id(demo_list)) demo_list.append(999) demo_list.pop(0) demo_list.remove(2) demo_list[0] = 10 print("修改資料後的記憶體地址 %d" % id(demo_list)) demo_dict = {"name": "小明"} print("定義字典後的記憶體地址 %d" % id(demo_dict)) demo_dict["age"] = 18 demo_dict.pop("name") demo_dict["name"] = "老王" print
("修改資料後的記憶體地址 %d" % id(demo_dict))

結果:

定義列表後的記憶體地址 64063240
修改資料後的記憶體地址 64063240
定義字典後的記憶體地址 6724168
修改資料後的記憶體地址 6724168

注意

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

雜湊 (hash)

  • Python 中內建有一個名字叫做 hash(o) 的函式
    • 接收一個 不可變型別 的資料作為 引數
    • 返回 結果是一個 整數
  • 雜湊 是一種 演算法,其作用就是提取資料的 特徵碼(指紋)
    • 相同的內容 得到 相同的結果
    • 不同的內容 得到 不同的結果
  • 在 Python 中,設定字典的 鍵值對 時,會首先對 key 進行 hash 已決定如何在記憶體中儲存字典的資料,以方便 後續 對字典的操作:增、刪、改、查
    • 鍵值對的 key 必須是不可變型別資料
    • 鍵值對的 value 可以是任意型別的資料

1.3  區域性變數和全域性變數

  • 區域性變數 是在 函式內部 定義的變數,只能在函式內部使用
  • 全域性變數 是在 函式外部定義 的變數(沒有定義在某一個函式內),所有函式 內部 都可以使用這個變數

提示:在其他的開發語言中,大多 不推薦使用全域性變數 —— 可變範圍太大,導致程式不好維護!

函式不能直接修改全域性變數的引用(不能直接,但是可以間接)

  • 在函式內部,可以 通過全域性變數的引用獲取對應的資料
  • 但是,不允許直接修改全域性變數的引用 —— 使用賦值語句修改全域性變數的值
舉一個例子
num = 10
def demo1():
    print("demo1" + "-" * 50)
    # 只是定義了一個區域性變數,不會修改到全域性變數,只是變數名相同而已,相當於在這裡定義了一個區域性變數100
    num = 100
    print(num)

demo1()
print("over")

在函式內部修改全域性變數的值(間接修改)

  • 如果在函式中需要修改全域性變數,需要使用 global 進行宣告
舉一個例子
num = 10
def demo1():
    print("demo1" + "-" * 50)
    # global 關鍵字,告訴 Python 直譯器 num 是一個全域性變數
    global num
    num = 100
    print(num)

demo1()
print("over")

全域性變數命名的建議

  • 為了避免區域性變數和全域性變量出現混淆,在定義全域性變數時,有些公司會有一些開發要求,例如:
  • 全域性變數名前應該增加 g_ 或者 gl_ 的字首

2  函式進階

2.1  函式的返回值 進階

  • 在程式開發中,有時候,會希望 一個函式執行結束後,告訴呼叫者一個結果,以便呼叫者針對具體的結果做後續的處理
  • 返回值 是函式 完成工作後,最後 給呼叫者的 一個結果
  • 在函式中使用 return 關鍵字可以返回結果
  • 呼叫函式一方,可以 使用變數 來 接收 函式的返回結果

使用函式返回多個值(元組)

def measure():
    """返回當前的溫度"""

    print("開始測量...")
    temp = 39
    wetness = 10
    print("測量結束...")

    # 返回的是一個元組的話,括號可以省略
    return (temp, wetness)

# 在 Python 中,可以 將一個元組 使用 賦值語句 同時賦值給 多個變數
# 注意:變數的數量需要和元組中的元素數量保持一致
result = temp, wetness = measure()

面試題 —— 交換兩個數字(python 獨有)

a = 10
b = 5
a, b = b, a
print("%d == %d" % (a,b))

結果:5 == 10

2.2  函式的引數 進階

不可變型別和可變型別的引數

問題 1:在函式內部,針對引數使用 賦值語句,會不會影響呼叫函式時傳遞的 實參變數? —— 不會!

無論傳遞的引數是 可變 還是 不可變

  • 只要 針對引數 使用 賦值語句,會在 函式內部 修改 區域性變數的引用不會影響到 外部變數的引用(這個是賦值操作,不呼叫方法)
def demo(num, num_list):
    print("函式內部")

    # 賦值語句
    num = 200
    num_list = [1, 2, 3]

    print(num)
    print(num_list)

    print("函式程式碼完成")


gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)

結果(函式外的不可變型別、可變型別都沒有因為函式內的賦值而改變)

函式內部
200
[1, 2, 3]
函式程式碼完成
99
[4, 5, 6]

問題 2:如果傳遞的引數是 可變型別,在函式內部,使用 方法 修改了資料的內容,同樣會影響到外部的資料

def mutable(num_list):

    num_list.extend([1, 2, 3])
    
    print(num_list)

gl_list = [6, 7, 8]
mutable(gl_list)
print(gl_list)

結果(通過呼叫方法在末尾新增元組[1, 2, 3],影響了外部的資料)
[6, 7, 8, 1, 2, 3]
[6, 7, 8, 1, 2, 3]

面試題 —— +=

  • 在 python 中,列表變數呼叫 += 本質上是在執行列表變數的 extend 方法,不會修改變數的引用
def mutable(num_list):
    num_list += [1, 2, 3]


gl_list = [6, 7, 8]
mutable(gl_list)
print(gl_list)

結果和上一樣

2.3  預設引數