您好,登錄后才能下訂單哦!
今天小編給大家分享一下Python函數進階的使用方法實例分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
假如有一串代碼,觀察其輸出結果:
def f(): a = 1 return a print(a) 輸出結果: Traceback (most recent call last): File "E:/python代碼/11/文件一.py", line 4, in <module> print(a) NameError: name 'a' is not defined報錯了!錯誤是“name 'a' is not defined”。變量a沒有被定義。。。為啥?我明明定義了a=1呀!
那我們就要了解一下Python代碼運行時遇到函數時怎么做的:
首先從python解釋器開始執行之后,就在內存中開辟了一個空間每當遇到一個變量的時候,就把變量名和值之間的對應關系記錄下來。但是當遇到函數定義的時候解釋器只是象征性的將函數名讀入內存,表示知道這個函數的存在了,至于函數內部的變量和邏輯解釋器根本不關心。等執行到函數調用的時候,python解釋器會再開辟一塊內存來存儲這個函數里的內容,這個時候,才關注函數里面有哪些變量,而函數中的變量會存儲在新開辟出來的內存中。函數中的變量只能在函數的內部使用,并且會隨著函數執行完畢,這塊內存中的所有內容也會被清空。
我們給這個“存放名字與值的關系”的空間起了一個名字——叫做命名空間
代碼在最開始創建的存儲“變量名與值的關系”的空間叫做全局命名空間,在函數內部運行中開辟的臨時的空間叫做局部命名空間
函數命名空間一共分為三大類
1、內置命名空間 —— python解釋器 # 就是python解釋器一啟動就可以使用的名字存儲在內置命名空間中 # 內置的名字在啟動解釋器的時候被加載進內存里 2、全局命名空間 —— 我們寫的代碼但不是函數中的代碼 # 是在程序從上到下被執行的過程中依次加載進內存的 # 放置了我們設置的所有變量名和函數名 3、局部命名空間 —— 函數 # 就是函數內部定義的名字 # 當調用函數的時候 才會產生這個名稱空間 隨著函數執行的結束 這個命名空間就又消失了 #在局部:可以使用全局、內置命名空間中的名字 #在全局:可以使用內置命名空間中的名字,但是不能用局部中使用 #在內置:不能使用局部和全局的名字的內置命名空間:內置命名空間中存放了Python解釋器為我們提供的名字(函數)我們不需要定義,都是我們熟悉的打開解釋器就能夠直接使用如:input、print、str、set……
加載順序:內置命名空間(程序運行前加載 > 全局命名空間(程序運行中:從上到下加載) > 局部命名空間(程序運行中:調用時才加載)
在局部調用時:局部命名空間 > 全局命名空間 > 內置命名空間
在全局調用時:全局命名空間 > 內置命名空間
例子:
a = 10 def f(): a = 1 print(a) f() print(a) 輸出結果: 1 10
作用域就是作用范圍,按照生效范圍可以分為全局作用域和局部作用域。
全局作用域:包含內置名稱空間、全局名稱空間,在整個文件的任意位置都能被引用、全局有效
局部作用域:局部名稱空間,只能在局部范圍內生效
locals():
函數會以字典類型返回當前位置的全部局部變量。globals():
函數會以字典類型返回當前位置的全部全局變量。def func(): a = 1 print(locals()) print(globals()) print('========================分割線==========================') func() print(locals()) print(globals())輸出結果:
1、global是Python中的全局變量關鍵字。
2、變量分為局部變量與全局變量,局部變量又可稱之為內部變量。
3、由某對象或某個函數所創建的變量通常都是局部變量,只能被內部引用,而無法被其它對象或函數引用。
4、全局變量既可以是某對象函數創建,也可以是在本程序任何地方創建。全局變量是可以被本程序所有對象或函數引用。
5、global關鍵字的作用是可以使得一個局部變量為全局變量例子:
在my函數中,在 x 前面加 global,my函數將 x 賦為8,此時全局變量中的 x 值改變。需要注意的是 global 需要在函數內部聲明,若在函數外聲明,則函數依然無法操作 x 。
x = 4 def my(): global x x = 8 print("x = ", x) print("x = ", x) my() print("x = ", x) 輸出結果是: x = 4 x = 8 x = 8
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 ret = max4(1,2,4,3) print(ret) 輸出結果: 4
def f1(): print("in f1") def f2(): print("in f2") f2() f1() 輸出結果: in f1 in f2 def f1(): def f2(): def f3(): print("in f3") print("in f2") f3() print("in f1") f2() f1() 輸出結果: in f1 in f2 in f3
a = 1 def outer(): a = 5 def inner(): a = 2 def inner2(): nonlocal a a += 1 print('inner2',a) inner2() print('##a##:',a) inner() print('**a**:',a) outer() print('全局:',a) 輸出結果: inner2 3 ##a##: 3 **a**: 5 全局: 1
#nonlocal 只能用于局部變量,找上層中離當前函數最近一層的局部變量且外部必須有這個變量 #聲明了nonlocal的內部函數的變量修改會影響到離當前函數最近一層的局部變量 #對全局無效,在內部函數聲明nonlocal變量之前不能再出現同名變量 #對局部也只是對最近一層有影響def f1(): a = 1 def f2(): nonlocal a a = 2 f2() print('a in f1 : ',a) f1() 輸出結果: a in f1 : 2
# 對于不可變數據類型 在局部可是查看全局作用域中的變量 # 但是不能直接修改 # 如果想要修改,需要在程序的一開始添加global聲明 # 如果在一個局部(函數)內聲明了一個global變量,那么這個變量在局部的所有操作將對全局的變量有效
函數名就是內存地址
函數名可以被賦值
函數名可以作為容器類型的元素
函數名可以作為函數的返回值
函數名可以作為函數的參數
def func(): print(123) func() print(func) # 函數名就是內存地址 # 函數名可以被賦值 func2 = func func2() #函數名可以作為容器類型的元素 l = [func,func2] for i in l: i() def func(): print(123) def wahaha(f): f() return f #函數名可以作為函數的返回值 qqxing = wahaha(func) #函數名可以作為函數的參數 qqxing() 輸出結果: 123 <function func at 0x000001ADF9946280> 123 123 123 123 123
如果我自己定義了一個input函數(作用:調用該函數就打印'在下周周ovo'),會不會與內置的input函數有沖突呢?
def input(a): print('在下周周ovo')那么接下來的代碼怎么運行呢?
def input(a): print('在下周周ovo') def func(): input('請輸入') print(input) func()答案:
內部函數包含對外部作用域而非全劇作用域名字的引用,該內部函數稱為閉包函數
#函數內部定義的函數稱為內部函數由于有了作用域的關系,我們就不能拿到函數內部的變量和函數了。如果我們就是想拿怎么辦呢?返回呀!
如果函數內的變量我們要想在函數外部用,可以直接返回這個變量,那么如果我們想在函數外部調用函數內部的函數呢?那就直接將函數名字作為返回值就好
def outer(): a = 1 def inner(): print(a) #內部函數調用了外部變量a return inner inn = outer() inn() 輸出結果: 1
判斷閉包函數的方法__closure__
當運行后,如果有cell的話,就表示是閉包函數。如果沒有就不是。
#輸出的__closure__有cell元素 :是閉包函數 def func(): name = 'eva' def inner(): print(name) print(inner.__closure__) return inner f = func() f() #輸出的__closure__為None :不是閉包函數 name = 'egon' def func2(): def inner(): print(name) print(inner.__closure__) return inner f2 = func2() f2() 輸出結果: (<cell at 0x000001E935CB0FA0: str object at 0x000001E935CC2CB0>,) eva None egon
顧名思義是兩個或以上的閉包函數嵌套在一起
def wrapper(): money = 10 def func(): name = 'zhou' def inner(): print(name,money) #引用了func()函數中name變量引用了wrapper()函數中money變量 return inner return func f = wrapper() i = f() i() 輸出結果: zhuo 10
#func(一個函數名) --->>對應函數的內存地址 #函數名()---函數調用 #函數的內存地址----()函數的調用 # 作用域兩種 # 全局作用域 —— 作用在全局 —— 內置和全局名字空間中的名字都屬于全局作用域 ——globals() # 局部作用域 —— 作用在局部 —— 函數(局部名字空間中的名字屬于局部作用域) ——#locals()globals() : 永遠打印全局的名字 #locals() : 輸出什么 根據locals所在位置 #在代碼中要盡量少定義全局變量,多使用返回值和接收返回值 #函數的嵌套: 嵌套調用 嵌套定義:定義在內部的函數無法直接在全局被調用 #函數名的本質: 就是一個變量,保存了函數所在的內存地址 #閉包: 內部函數包含對外部作用域而非全劇作用域名字的引用,該內部函數稱為閉包函數
以上就是“Python函數進階的使用方法實例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。