<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
未使用global情況:
# 在外部繫結一個變數名 name = 'kangkng' # 定義一個函數體程式碼 def func(): # 函數體內部重新系結一個變數名 name = 'zhangzhang' # 呼叫函數func func() # 這時無法列印函數體內部的變數名 print(name) ------------------------------------------------------------------------ kangkang
使用global情況:
# 在函數體內部使用global時,可在外部直接呼叫函數內部變數名 name = 'kangkng' # 定義一個函數體程式碼 def func(): # 使用global呼叫變數名 global name # 函數體內部重新系結一個變數名 name = 'zhangzhang' # 呼叫函數func func() # 外py中列印name print(name) ------------------------------------------------------------------------ zhangzhang
而nonlocal的作用是,可以在父程式碼中直接呼叫子程式碼中的變數名,條件是需要在子程式碼中使用nonlocal 呼叫需要的變數名
未使用nonlocal情況:
# 定義一個函數體程式碼 def outer(): # 繫結一個變數名 name = 'kangkang' # 程式碼體內部再次定義一段函數體 def subcoat(): # 內層中繫結變數名 name = 'zhangzhang' # 在函數外層列印變數名 print(name) # 呼叫外層函數體程式碼 outer() ----------------------------------------------------------------------- kangkang
使用nonlocal情況:
# 在函數體內部使用global時,可在外部直接呼叫函數內部變數名 def outer(): # 函數外層繫結一個變數名 name = 'kangkang' # 程式碼體內部再次定義一段函數體 def subcoat(): # 在函數體內層使用nonlocal,呼叫變數名 nonlocal name # 內層中繫結變數名 name = 'zhangzhang' # 呼叫內層函數 subcoat() # 在函數外層列印變數名 print(name) # 呼叫外層函數體程式碼 outer() ---------------------------------------------------------------------- zhangzhang
引言:
函數名就相當於變數名,只不過函數名系結的是一段函數體程式碼,在我們使用這個函數名加括號時就可以呼叫這段程式碼體,具體由以下幾種用法:
1、當做變數名賦值
def func(): print('我是func函數體程式碼') res = func print(res()) ------------------------------------------------------------------------ 我是func函數體程式碼 None
2、當作函數的引數
def func(): print('我是func函數體程式碼') def func1(a): print('我是func1函數體程式碼', a) a() func1(func) ------------------------------------------------------------------------ 我是func1函數體程式碼 <function func at 0x000001D0C14D6310> 我是func函數體程式碼
3、當作函數的返回值
def func(): print('我是func函數體程式碼') def func1(): print('我是func1函數體程式碼') return func res = func1() print(res) res() ------------------------------------------------------------------------ 我是func1函數體程式碼 <function func at 0x00000218F95B6310> 我是func函數體程式碼
4、當作容器型別的資料
def spring(): print('我是春季,生機盎然') def summer(): print('我是夏季,活力四射') def autumn(): print('我是秋季,翩翩起舞') def winter(): print('我是冬季,大雪紛飛') while True: season_dict = { '1': spring, '2': summer, '3': autumn, '4': winter } season_select = input('根據編號,選擇您喜歡的季節>>>:').strip() if season_select in season_dict: season_dict.get(season_select)() else: print('你選擇的編號不存在') ------------------------------------------------------------------------
一個函數的返回值是另外一個函數,返回的函數呼叫父函數內部的變數,如果返回的函數在外部被執行,就產生了閉包
滿足以下兩個條件的就是閉包函數:
條件一:定義在函數內部的函數
條件二:用到了外部函數空間名稱中的名子
作用:使函數外部能夠呼叫函數內部放入屬性和方法
缺點:閉包操作導致整個函數的內部環境被長久儲存,佔用大量記憶體
1.函數內部變數名在外部被存取
def fun1(): name = 'python' def inner(): print(name) return inner result = fun1() result() ------------------------------------------------------------------------ python
2.函數體內部函數體程式碼可以通過外部存取
def fun2(): def inner(): print("執行了內部函數inner") def all(): return inner return all result = fun2() result()() ------------------------------------------------------------------------ 執行了內部函數inner
當我們需要將一段函數體程式碼在不改變呼叫方式和原始碼的情況下,需要給這個段程式碼新增新的功能時,這時候我們就需要給這段程式碼安裝一個裝飾器,裝飾器是指將這段程式碼封裝在閉包函數內,來達到既能滿足上述條件,又能增加新的功能的條件
概念
本質
口訣
1、首先定義一段函數體程式碼,當我們給這段函數傳入指定的引數時,他就會暫停一秒,然後執行,使它在執行結束後,能夠統計它的執行時間
import time def index(a, b): time.sleep(1) print(index,a, b)
2、通常,我們只需要在這段程式碼執行前列印一個時間戳,執行後再次列印一個時間戳,在這段程式碼執行結束後通過前後時間的插值就能統計出這段程式碼的執行時間,但這種辦法使用起來比較麻煩且只能使用一次
方法一: import time def index(a, b): start = time.time() time.sleep(1) print(index, a, b) end = time.time() print(end - start) index(1,2) 方式二: import time def index(a, b): time.sleep(1) print(index, a, b) start = time.time() index(1,2) end = time.time() print(end - start)
3、通過上述方法的方式二,我們可以得出將函數名包裹在統計時間功能程式碼內,這樣在呼叫時相對便捷,進一步思考,若將這段程式碼使用函數封包,那樣在呼叫時就可以更為便捷,在以後統計該程式碼時,只需要呼叫封包這段程式碼的函數名就可以直接統計這段程式碼的執行時間
import time def index(a, b): time.sleep(1) print(index, a, b) def time_(): start = time.time() index() end = time.time() print(end - start) time_() ------------------------------------------------------------------------ Traceback (most recent call last): File "D:/pytcharm專案檔案路徑/38/11.py", line 297, in <module> time_() File "D:/pytcharm專案檔案路徑/38/11.py", line 293, in time_ index() TypeError: index() missing 2 required positional arguments: 'a' and 'b'
4、雖然這種方式可以行得通,但只能針對沒有引數的函數體程式碼,若這段程式碼需要傳參者無法執行,並直接報錯。再次進一步思考,只需要將封包的這段函數設定為有參函數就可解決這個問題
import time def index(a, b): time.sleep(1) print(index, a, b) def core(a,b): start = time.time() index(a, b) end = time.time() print(end - start) core(1, 2) ------------------------------------------------------------------------ <function index at 0x000001F4A0026310> 1 2 1.0047826766967773
5、由上推導可看出,雖然此功能可以更為便捷的統計程式碼執行時間,但若是原始碼的引數需要修改則封包它的引數也需要修改,這時我們可聯想到將引數修改為可變長引數,就不會出現這個問題
import time def index(a, b): time.sleep(1) print(index, a, b) def core(*args,**kwargs): start = time.time() index(*args, **kwargs) end = time.time() print(end - start) core(1,2) ------------------------------------------------------------------------ <function index at 0x000002ECDD4E6310> 1 2 1.004744529724121
6、這樣無論原始碼引數如何修改,我們都可以進行傳參,雖然這個問題解決了,但考慮使用的廣泛性,若有其他函數體也需要用到這個功能時,還需要重新修改封包內程式碼,這時,我們可以使用閉包的方式來滿足這個條件
import time def index(a, b): time.sleep(1) print(index, a, b) def func(x, y, z): time.sleep(2) print(func, x, y, z) def outer(index): def core(*args, **kwargs): start = time.time() index(*args, **kwargs) end = time.time() print(end - start) return core res = outer(func) res(1, 2, 3) ------------------------------------------------------------------------ <function func at 0x0000018C23686670> 1 2 3 2.00856614112854
7、通過將原始碼函數名放至閉包函數引數內,就可以達到可以調動任何函數體程式碼都可以執行此功能的方法,但並未滿足閉包函數的條件,原始碼的呼叫方式改變了,這時我們可以通過將原函數體程式碼賦值的方式來達到呼叫方式和原始碼都未改變的情況下來增加此功能
import time def index(a, b): time.sleep(1) print(index, a, b) def func(x, y, z): time.sleep(2) print(func, x, y, z) def outer(index): def core(*args, **kwargs): start = time.time() index(*args, **kwargs) end = time.time() print(end - start) return core index = outer(index) index(1,2) func = outer(func) func(1, 2, 3) ------------------------------------------------------------------------ <function outer.<locals>.core at 0x0000026C17F58280> 1 2 1.004807710647583 <function outer.<locals>.core at 0x0000026C17F58940> 1 2 3 2.0077626705169678
8、雖然上述推導過程都已滿足裝飾器條件,但是考慮到原始碼有返回值的情況,我們沒有並沒有獲取,這時在進一步推導,可在裝飾器函數內部呼叫原始碼函數名的位置設定一個變數名用於接收返回值,傳給裝飾器底層return用於接收即可解決這個問題
import time def index(a, b): time.sleep(1) print(index, a, b) return 'index' def func(x, y, z): time.sleep(2) print(func, x, y, z) return 'func' def outer(index): def core(*args, **kwargs): start = time.time() res = index(*args, **kwargs) end = time.time() print(end - start) return res return core index = outer(index) res = index(1,2) print(res) func = outer(func) res = func(1, 2, 3) print(res) ------------------------------------------------------------------------ <function outer.<locals>.core at 0x0000020C50A78280> 1 2 1.0050580501556396 index <function outer.<locals>.core at 0x0000020C50A78940> 1 2 3 2.0094454288482666 func
什麼是裝飾器語法糖
當我們使用裝飾器呼叫被裝飾的函數體程式碼時,總是需要在呼叫前通過賦值的方式來呼叫,這樣的方式相對比較麻煩,這時我們就可以用到裝飾器語法糖來節省時間和程式碼
語法糖的使用方法和條件
用法:在原始碼函數體上方使用@加裝飾器函數名
條件:原始碼需在裝飾器下方
具體用法
import time def outer(index): def core(*args, **kwargs): start = time.time() res = index(*args, **kwargs) end = time.time() print(end - start) return res return core @outer def index(a, b): time.sleep(1) print(index, a, b) return 'index' index(1,2)
def outer(func): def inner(*args, **kwargs): # 執行被裝飾物件之前可以做的額外操作 res = func(*args, **kwargs) # 執行被裝飾物件之後可以做的額外操作 return res return inner
以上就是Python基礎globlal nonlocal和閉包函數裝飾器語法糖的詳細內容,更多關於Python基礎globlal nonlocal的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45