?Python之路---函式進階✔️
程式設計師三大美德:
- 懶惰
因為一直致力於減少工作的總工作量。
- 缺乏耐性
因為一旦讓你去做本該計算機完成的事,你將會怒不可遏。
- 傲慢
因為被榮譽感衝暈頭的你會把程式寫得讓誰都挑不出毛病來。
大家好?, 現在讓我們一起來學習一下函式進階部分的內容?
? 藥引
我們在前面學會了函式的基本使用,那麼我們來看以下的程式碼:
def myfunc(x, y):
m = x + y
myfunc(10, 20)
print(m)
so ?, 執行程式碼:
NameError: name 'm' is not defined
報錯了!程式猿?最怕的並不是報錯,而是報的錯誤解決不了。
我們來看下這個報錯,“name 'm' is not defined”,變數m沒有被定義?,但是我們明明在函式內定義了!
首先,我們看看上篇文章中的一張圖片,瞭解下程式碼執行時遇到函式是怎麼做的:
1. 從Python直譯器開始執行之後,就會在記憶體中開闢一個空間
2. 每當遇到一個變數時,就會把變數名和值的對應關係儲存下來
但是當遇到函式定義時,直譯器只是象徵性的把函式名讀入記憶體,表示知道有這個函式存在了,而函式內部的變數和邏輯,直譯器不關心。
3. 等呼叫函式時,python直譯器會在開闢一塊記憶體來儲存函式裡的內容,這個時候才關注函式裡面有哪些變數,而函式中的變數只能在函式內部使用,並且會隨著函式執行完畢,這塊記憶體中的內容會被清空(垃圾回收)
這就是為什麼變數m沒有定義的原因?
而我們給這個“存放名字與值”的空間起來一個名字---名稱空間
名稱空間是一種絕妙的理念,讓我們盡情的使用發揮吧!----《Python之禪》
名稱空間
名稱空間一共分為三種:
- 全域性名稱空間---程式碼在執行伊始,建立的儲存“變數名與值的關係”的空間
- 區域性名稱空間---在函式的執行中開闢的臨時的空間
- 內建名稱空間---程式執行前載入
PS:*內建名稱空間中存放了python直譯器為我們提供的名字:input,print,str,list,tuple...它們都是我們拿過來就可以用的方法。
載入順序:內建名稱空間-->全域性名稱空間-->區域性名稱空間
取值順序:區域性名稱空間-->全域性名稱空間-->內建名稱空間
作用域
作用域就是作用範圍(銅鑼灣陳浩南?)
按照生效範圍分為:
- 全域性作用域:包含內建名稱空間、全域性名稱空間,在整個檔案的任意位置都能被引用、全域性有效
- 區域性作用域:區域性名稱空間,只能在區域性範圍內生效
global
global關鍵字的作用:全域性宣告
a = 10
def func():
global a
a = 20
print(a)
func()
print(a)
函式巢狀
我們學過if語句巢狀,for迴圈巢狀,其實函式也可以巢狀
函式巢狀定義
def f1():
print("in f1")
def f2():
print("in f2")
f2()
f1()
函式巢狀呼叫
def max2(x, y):
'''比較兩個數的大小'''
m = x if x > y else y
return m
def max4(a, b, c, d):
res1 = max2(a, b)
res2 = max2(res1, c)
res3 = max2(res2, d)
return res3
the_max = max4(23, -7, 30, 11)
print(the_max)
函式名
函式名本質上就是函式的記憶體地址
def func():
print('in func')
print(func) # output:<function func at 0x0000019B7FF22EA0>
-
可以被引用
def func(): print('in func') f = func print(f)
-
可以被當作容器型別的元素
PS: 一句話,可以當成普通變數用
閉包
內部函式包含對外部作用域而非全劇作用域名字的引用,該內部函式稱為閉包函式
閉包的常用的用法:
def func(): # 外部函式
name = 'mark'
def inner(): # 內部函式
print(name)
print(inner.__closure__) #判斷閉包函式的方法
return inner
f = func()
f()
總結
名稱空間:
函式的巢狀:
巢狀定義:定義在內部的函式無法直接在全域性被呼叫
函式名的本質:
就是一個變數,儲存了函式所在的記憶體地址
閉包:
內部函式包含對外部作用域而非全劇作用域名字的引用,該內部函式稱為閉包函式