09-Python之路—函數進階
🐴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()
總結
命名空間:
函數的嵌套:
嵌套定義:定義在內部的函數無法直接在全局被調用
函數名的本質:
就是一個變數,保存了函數所在的記憶體地址
閉包:
內部函數包含對外部作用域而非全劇作用域名字的引用,該內部函數稱為閉包函數