1. 程式人生 > >預設引數的陷阱

預設引數的陷阱

預設引數的陷阱 : 預設引數實際上只有一個值
如果是可變資料型別,無論這個函式被呼叫多少次,
共用這個預設引數
a = []
b = []
a.append(1)
print(a,b)

a = []
b = a
a.append(1)
print(a,b)

變數是變數,值是值
變數的名字和有多少個值 沒有對應關係
我們在看修改的時候 : 要看修改的是哪一個具體的值而不是變數

l = [] # 在定義函式之前定義了一個[]
def func():
l.append(1)
func()
func()
func()
func()

def func(l = []): # 在函式定義的時候 建立了一個[]
# 對於預設引數來說,[]只定義一次
l.append(1)

func()
func([]) # 又建立了一個新的空列表,傳給func,代替l=[]這個預設引數
func()
func()

def func2(a = 0): # 在函式定義的時候,建立了一個值 0,只有一個0,a永遠不消失
a += 1 # a = 0 + 1 = 1 區域性變數 會隨著這個函式的呼叫而消失
print(a)

func2()
func2()
func2()
func2()

l = []
l.append(1)
演算法 : 超過4個值 把這個列表擴大一倍

函式 是 第一類物件的概念
函式名 可以賦值\可以做引數\做返回值\容器型別中的一項(可以作為字典的key)
函式的記憶體地址() ==> 呼叫這個函式
函式的函式名會改變麼 ??? 不會改變

閉包 : 快取和裝飾器
內部函式引用了外部函式的變數,內部函式就是一個閉包
def outer():
a = 1
# 先來計算/執行程式碼 獲得要快取的值
def inner():
'''引用一個外部函式的變數a'''
'''引用外部快取的值'''
return inner # inner 函式的記憶體地址

inn = outer()
inn()
inn()


快取 把一個值儲存在記憶體裡
如果一個值 在網路上存,那麼你想拿到這個值需要聯網 下載 (消耗時間)
如果一個值 要通過複雜的計算才能得出結果,那麼每一次你想拿到這個值都要重新計算一次(消耗時間)

裝飾器 本質就是一個閉包
一個函式寫完之後就不能修改了,這個時候想在這個函式之前或者之後新增一些功能 就用裝飾器