欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

怎么理解Python變量作用域

這篇文章主要介紹“怎么理解Python變量作用域”,在日常操作中,相信很多人在怎么理解Python變量作用域問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解Python變量作用域”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

十載專注建站、設計、互聯(lián)網(wǎng)產(chǎn)品按需開發(fā)網(wǎng)站服務,業(yè)務涵蓋高端網(wǎng)站設計、成都做商城網(wǎng)站、小程序制作、軟件系統(tǒng)開發(fā)、app軟件開發(fā)公司等。憑借多年豐富的經(jīng)驗,我們會仔細了解每個客戶的需求而做出多方面的分析、設計、整合,為客戶設計出具風格及創(chuàng)意性的商業(yè)解決方案,成都創(chuàng)新互聯(lián)更提供一系列網(wǎng)站制作和網(wǎng)站推廣的服務,以推動各中小企業(yè)全面信息數(shù)字化,并利用創(chuàng)新技術(shù)幫助各行業(yè)提升企業(yè)形象和運營效率。

閉包就是, 函數(shù)內(nèi)部嵌套函數(shù). 而 裝飾器只是閉包的特殊場景而已, 特殊在如果外函數(shù)的參數(shù)是指向一個, 用來被裝飾的函數(shù)地址時(不一定是地址哈, 隨意就好) , 就有了 "@xxx" 這樣的寫法, 還是蠻有意思的. 裝飾器的作用是 在不改變原函數(shù)的代碼前提下, 額外給原函數(shù)填寫新功能. 寫法上來看, 還是比較簡潔優(yōu)雅的.

裝飾器的通俗寫法

# 裝飾器的通用寫法def out(func):  def inner(*args, **kwargs):    print("we are checking...", args[0])    return func(*args, **kwargs)  return inner@outdef check_2019_nCov(name):  return f"now, {name} is very healthy..."tmp = check_2019_nCov('youge')print(tmp)# outputwe are checking... yougenow, youge is very healthy...

給裝飾器傳參

雖然這種 "@" 的寫法, 是要求 外函數(shù)的參數(shù)是一個 func 地址 , 但要達到可以傳參, 只要 再在外面包一層函數(shù) (作用是接受參數(shù)) , 這樣不就相當于擴大作用空間, 拿到參數(shù)了呀 .

# 最外層的函數(shù)作用是, 給裝飾器傳遞參數(shù)def get_param(*args, **kwargs):  def out(func):    def inner(*args, **kwargs):      print("get params", args, kwargs)      return func(*args, **kwargs)    return inner  return out@get_param("youge")def check_2019_nCov(name):  return f"now, {name} is very healthy..."tmp = check_2019_nCov("youge")print(tmp)# outputget params ('youge',) {}now, youge is very healthy...

這種個裝飾器傳遞參數(shù)的應用場景, 在 Web應用中, 以 Flask 為例, 就是所有的 路由 url 的概念呀, 如 route("/login") 這樣的寫法, 其原理就是用各種裝飾器來實現(xiàn) 路由 -> 視圖 的映射關(guān)系的.

仔細一看, 整個過程忽略了一個重要的話題, 即命名空間, 及 變量的作用域, 或者說命名空間如怎樣的.

LEGB 法則

命名空間

前篇已經(jīng)詳細闡述過了, Python 變量的本質(zhì)是指針, 是對象的引用, 而 Python中 萬物皆對象. 這個對象是真正存儲數(shù)據(jù)的內(nèi)存地址, 是各種類(數(shù)據(jù)類型, 數(shù)據(jù)結(jié)構(gòu)) 的實例. (變量就是用來引用對象的) 差不多這個意思吧.

最為直觀的解釋:

" A namespace is a mapping from names to objects". (變量名和對象的映射)

"Most namespaces are currently implemented as Python dictionaries." (大部分命名空間通過字典來實現(xiàn))

即命名空間是用來 避免變量命名沖突 的約束. 各個命名空間是彼此獨立的, 一個空間中不能重名, 不同空間中是不沒有關(guān)系的. 就跟 計算機系統(tǒng), 存儲文件是樣的邏輯.

for i in range(10):  print(i)# 這兩句話都用到了 i 但其各自的空間是不一樣的.[i for i in range(100)]

內(nèi)置空間: (built-in names): Python 內(nèi)置名稱, 如內(nèi)置函數(shù),異常類...全局空間: (global names): 常量, 模塊中定義的名稱(類, 導入模塊)...Enclosed: 可能嵌套在函數(shù)內(nèi)的函數(shù)等...局部名稱: (local names): 函數(shù)中定義的名稱(函數(shù)內(nèi)的變量) ...

Python 查找變量順序為:Local -> Enclosed -> Global -> Built-in。

其實, 從我個人經(jīng)驗而言, 能區(qū)分 局部和全局 的 相對性. 就好了, 基本上. 直觀上, 以一個寫代碼的 py文件為例. 最外層有, 變量, 類定義, 函數(shù)定義, 從from .. import .. 的變量或函數(shù)名, 這些就是 全局變量, 最外面的類或者函數(shù), 里面是各自的名字空間呀.

# var1 是 globalvar1 = 666def foo():  # var2 是局部  var2 = 666  def foo2():    # 內(nèi)嵌的局部    var3 = 666    # print(var2)print(var3) # G->L 是找不到的哦# 在 foo2 中 尋找 var2 是 L->E 是ok的# 在 foo 中 尋找 var2 是 E->L 是不行的

其實很好理解的. 就上段code來說,根據(jù) L-E-G-B 法則, 其實理解一個 相對 就可以了.

全局 vs 局部

total = 0 # 全局def sum(a, b):  """重寫內(nèi)置sum"""  total = a + b  print("局部total:", total)sum(1, 1)print("全局total:", total)# output局部total: 2全局total: 0

可以看到, 局部是不會改變?nèi)值呐? 而在局部內(nèi)是可以拿到全局變量的. 不然閉包, 外函數(shù)接收的參數(shù), 內(nèi)函數(shù)怎么可以拿到呢? 就是外函數(shù), "擴充了" 內(nèi)函數(shù)的作用域呀, 根據(jù) L->E->G->B 法則去搜索到.

global 和 nonlocal

name = "youge"def change_name():  name = "youyou"# 希望將 "youge" 改為 "youyou"change_name()print(name)# outputyouge

發(fā)現(xiàn)沒有能改掉, 這是自然的. 因為, 在調(diào)用函數(shù)時, 里面的 name 是一個 Local 變量, 是不會影響到全局的 name的, 如果想實現(xiàn)在 在函數(shù)內(nèi)部來改變 全局變量, 則將 該變量用 global 關(guān)鍵字聲明即可.

name = "youge"def change_name():  global name  name = "youyou"# 希望將 "youge" 改為 "youyou"change_name()print(name)# outputyouyou

很簡單, 在函數(shù)內(nèi)部, 用 global 將其聲明為全局變量即可. 同樣, 針對于** 函數(shù)嵌套, 即向閉包, 裝飾器等, 通過 關(guān)鍵字 nonlocal 實現(xiàn)將 函數(shù)內(nèi)的變量, 聲明為 函數(shù)外的 Enclose 層**

name = "jack"def outer():  name = "youge"  # 函數(shù)內(nèi)有一個local函數(shù)空間  def inner():    name = "youyou"    print("local:", name)  inner() # 嘗試改掉 嵌套層的 name  print("encolse:", name)print("global:", name)outer()# outputglobal: jacklocal: youyouencolse: youge

現(xiàn)在想在, inner函數(shù) (L層) 中來修改 E 層的 name, 即在inner中將 name 聲明為 nonlocal 即可.

name = "jack"def outer():  name = "youge"  # 函數(shù)內(nèi)有一個local函數(shù)空間  def inner():    nonlocal name    name = "youyou"    print("local:", name)  inner() # 嘗試改掉 嵌套層的 name  print("encolse:", name)print("global:", name)outer()# outputglobal: jacklocal: youyouencolse: youyou

函數(shù)嵌套場景中, 通過 在 local 層, 聲明 name 為 nonlocal 則將 enclosed 層的name改掉了. 但如果在 local 層 聲明 global 則是沒有其效果的, 為啥, 嗯... 暫時還不清楚, 也是實驗的, 暫時.

哦, 突然想貼一個, 我還是菜鳥時常, 犯的小錯誤:

name = 'youge'def change_name():  name = name + "youyou"change_name()print(name)# outputUnboundLocalError: local variable 'name' referenced before assignment

原因就在于, 在函數(shù)內(nèi)部的空間中, 對 name 是沒有定義的. 在 Python中, 對于函數(shù)過程的存儲, 是通過 遞歸棧 實現(xiàn)的. 利用棧的 FILO, (先進后出) 的特點, 當遇到一個函數(shù), 就用棧將其參與的成員, 依次入棧, 如有 return 則將置為棧元素.

變量要先定義, 后使用嘛, Python中的定義是指, 該變量指向某個實例對象即可, 而非 其它語言中的 類型聲明 哦, 這里最容易混淆.

修改 name 為全局變量,通過函數(shù)參數(shù)傳遞即可:

# 方式1: 定義個單獨的函數(shù)來處理name = 'youge'def change_name(s):  name = s + "youyou"  print(name)# 全局變量來傳遞給 函數(shù)空間, 即"先定義, 后執(zhí)行")change_name(name)  # outputyougeyouyou

# 方式2: 聲明為全局即可, 不推薦name = 'youge'def change_name():  global name  name = name + "youyou"change_name()print(name)# outputyougeyouyou

到此,關(guān)于“怎么理解Python變量作用域”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

分享名稱:怎么理解Python變量作用域
網(wǎng)址分享:http://chinadenli.net/article28/giogjp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、網(wǎng)站排名、響應式網(wǎng)站、用戶體驗、網(wǎng)站建設、云服務器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設計