最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python變量作用域LEGB用法解析

 更新時(shí)間:2020年02月04日 08:38:31   作者:小陳同學(xué)的數(shù)據(jù)之路  
這篇文章主要介紹了Python變量作用域LEGB用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了Python變量作用域LEGB用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

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

裝飾器的通俗寫(xiě)法

# 裝飾器的通用寫(xiě)法
def out(func):
  def inner(*args, **kwargs):
    print("we are checking...", args[0])
    return func(*args, **kwargs)

  return inner
@out
def check_2019_nCov(name):
  return f"now, {name} is very healthy..."


tmp = check_2019_nCov('youge')
print(tmp)

# output
we are checking... youge
now, youge is very healthy...

給裝飾器傳參

雖然這種 "@" 的寫(xiě)法, 是要求 外函數(shù)的參數(shù)是一個(gè) func 地址 , 但要達(dá)到可以傳參, 只要 再在外面包一層函數(shù) (作用是接受參數(shù)) , 這樣不就相當(dāng)于擴(kuò)大作用空間, 拿到參數(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)

# output
get params ('youge',) {}
now, youge is very healthy...

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

仔細(xì)一看, 整個(gè)過(guò)程忽略了一個(gè)重要的話題, 即命名空間, 及 變量的作用域, 或者說(shuō)命名空間如怎樣的.

LEGB 法則

命名空間

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

最為直觀的解釋:

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

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

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

for i in range(10):
  print(i)
  
# 這兩句話都用到了 i 但其各自的空間是不一樣的.
  
[i for i in range(100)]
  • 內(nèi)置空間: (built-in names): Python 內(nèi)置名稱(chēng), 如內(nèi)置函數(shù),異常類(lèi)...
  • 全局空間: (global names): 常量, 模塊中定義的名稱(chēng)(類(lèi), 導(dǎo)入模塊)...
  • Enclosed: 可能嵌套在函數(shù)內(nèi)的函數(shù)等...
  • 局部名稱(chēng): (local names): 函數(shù)中定義的名稱(chēng)(函數(shù)內(nèi)的變量) ...

Python 查找變量順序?yàn)椋篖ocal -> Enclosed -> Global -> Built-in。

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

# var1 是 global
var1 = 666

def 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 是不行的

其實(shí)很好理解的. 就上段code來(lái)說(shuō),根據(jù) L-E-G-B 法則, 其實(shí)理解一個(gè) 相對(duì) 就可以了.

全局 vs 局部

total = 0 # 全局

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

# output
局部total: 2
全局total: 0

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

global 和 nonlocal

name = "youge"

def change_name():
  name = "youyou"
  

# 希望將 "youge" 改為 "youyou"
change_name()
print(name)

# output
youge

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

name = "youge"

def change_name():
  
  global name
  name = "youyou"

# 希望將 "youge" 改為 "youyou"
change_name()
print(name)

# output
youyou

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

name = "jack"

def outer():
  name = "youge"

  # 函數(shù)內(nèi)有一個(gè)local函數(shù)空間
  def inner():
    name = "youyou"
    print("local:", name)

  inner() # 嘗試改掉 嵌套層的 name
  print("encolse:", name)


print("global:", name)

outer()

# output
global: jack
local: youyou
encolse: youge

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

name = "jack"

def outer():
  name = "youge"

  # 函數(shù)內(nèi)有一個(gè)local函數(shù)空間
  def inner():
    nonlocal name
    name = "youyou"
    print("local:", name)

  inner() # 嘗試改掉 嵌套層的 name
  print("encolse:", name)


print("global:", name)

outer()


# output 
global: jack
local: youyou 
encolse: youyou

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

哦, 突然想貼一個(gè), 我還是菜鳥(niǎo)時(shí)常, 犯的小錯(cuò)誤:

name = 'youge'
def change_name():
  name = name + "youyou"

change_name()  
print(name)

# output
UnboundLocalError: local variable 'name' referenced before assignment

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

變量要先定義, 后使用嘛, Python中的定義是指, 該變量指向某個(gè)實(shí)例對(duì)象即可, 而非 其它語(yǔ)言中的 類(lèi)型聲明 哦, 這里最容易混淆.

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

# 方式1: 定義個(gè)單獨(dú)的函數(shù)來(lái)處理
name = 'youge'

def change_name(s):
  name = s + "youyou"
  print(name)

# 全局變量來(lái)傳遞給 函數(shù)空間, 即"先定義, 后執(zhí)行")

change_name(name)  

# output
yougeyouyou
# 方式2: 聲明為全局即可, 不推薦
name = 'youge'

def change_name():
  global name
  name = name + "youyou"

change_name()
print(name)

# output
yougeyouyou

小結(jié)

  • 閉包, 裝飾器的本質(zhì)是函數(shù)的嵌套, 參數(shù)及函數(shù)能被傳遞的原因是, Pyhton變量的本質(zhì)是之指針
  • Python中用 命名空間 來(lái) 解決 變量名沖突, 原理跟 計(jì)算機(jī)系統(tǒng)(如 Linux) 存儲(chǔ)文件是一樣的邏輯
  • 變量名尋找的規(guī)則為 Local -> Enclosed -> Global -> Built-in
  • 個(gè)人覺(jué)得能理解,全局與局部的"相對(duì)性" 即可, 另外, 可用 global 與 nonlocal (E層) 改變變量作用等級(jí).
  • 變量作用域, 一直在用, 但卻經(jīng)常忽略它, 這里做個(gè)總結(jié), 沒(méi)事常翻翻, 作用域, 就到這吧.

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Webots下載安裝?+?Pycharm聯(lián)調(diào)使用教程

    Webots下載安裝?+?Pycharm聯(lián)調(diào)使用教程

    Webots是一個(gè)開(kāi)源的三維移動(dòng)機(jī)器人模擬器,它最初是作為研究移動(dòng)機(jī)器人中各種控制算法的研究工具開(kāi)發(fā)的,自2018年12月起,Webots作為開(kāi)源軟件發(fā)布,并獲得Apache 2.0許可證,這篇文章主要介紹了Webots下載安裝?+?Pycharm聯(lián)調(diào)?,需要的朋友可以參考下
    2023-02-02
  • python導(dǎo)入模塊交叉引用的方法

    python導(dǎo)入模塊交叉引用的方法

    今天小編就為大家分享一篇python導(dǎo)入模塊交叉引用的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Windows中使用wxPython和py2exe開(kāi)發(fā)Python的GUI程序的實(shí)例教程

    Windows中使用wxPython和py2exe開(kāi)發(fā)Python的GUI程序的實(shí)例教程

    wxPython是一款集成了Python的圖形化類(lèi)庫(kù)的工具,而py2exe是一款將Python程序轉(zhuǎn)換為exe可執(zhí)行文件的程序,二者搭配可以輕松地在Windows中創(chuàng)建圖形化程序,這里我們就來(lái)學(xué)習(xí)Windows中使用wxPython和py2exe開(kāi)發(fā)Python的GUI程序的實(shí)例教程:
    2016-07-07
  • python 自動(dòng)監(jiān)控最新郵件并讀取的操作

    python 自動(dòng)監(jiān)控最新郵件并讀取的操作

    這篇文章主要介紹了python 自動(dòng)監(jiān)控最新郵件并讀取的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • python處理中文編碼和判斷編碼示例

    python處理中文編碼和判斷編碼示例

    在開(kāi)發(fā)自用爬蟲(chóng)過(guò)程中,有的網(wǎng)頁(yè)是utf-8,有的是gb2312,有的是gbk,如果不加處理,采集到的都是亂碼,解決的方法是將html處理成統(tǒng)一的utf-8編碼
    2014-02-02
  • pytorch中的dataloader使用方法詳解

    pytorch中的dataloader使用方法詳解

    這篇文章主要介紹了pytorch中的dataloader使用方法詳解,構(gòu)建自己的dataloader是模型訓(xùn)練的第一步,本篇文章介紹下pytorch與dataloader以及與其相關(guān)的類(lèi)的用法,需要的朋友可以參考下
    2023-11-11
  • python 基于Appium控制多設(shè)備并行執(zhí)行

    python 基于Appium控制多設(shè)備并行執(zhí)行

    這篇文章主要介紹了python 如何基于Appium控制多設(shè)備并行執(zhí)行,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • python中pop()函數(shù)的語(yǔ)法與實(shí)例

    python中pop()函數(shù)的語(yǔ)法與實(shí)例

    這篇文章主要給大家介紹了關(guān)于python中pop()函數(shù)語(yǔ)法與實(shí)例的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Python?獲取指定開(kāi)頭指定結(jié)尾所夾中間內(nèi)容(推薦)

    Python?獲取指定開(kāi)頭指定結(jié)尾所夾中間內(nèi)容(推薦)

    獲取文章中指定開(kāi)頭、指定結(jié)尾中所夾的內(nèi)容。其中,開(kāi)頭和結(jié)尾均有多種,但最多也就十幾種,所以代碼還是具有可行性的,今天小編給大家介紹通過(guò)Python?獲取指定開(kāi)頭指定結(jié)尾所夾中間內(nèi)容,感興趣的朋友一起看看吧
    2023-02-02
  • Python深入學(xué)習(xí)之裝飾器

    Python深入學(xué)習(xí)之裝飾器

    這篇文章主要介紹了Python深入學(xué)習(xí)之裝飾器,裝飾器(decorator)是一種高級(jí)Python語(yǔ)法,本文全面介紹了Python中的裝飾器,需要的朋友可以參考下
    2014-08-08

最新評(píng)論

蒙城县| 翁牛特旗| 宝丰县| 肥东县| 牟定县| 出国| 山东省| 上饶市| 大厂| 霸州市| 丰县| 二连浩特市| 湾仔区| 海原县| 渭南市| 轮台县| 墨玉县| 铜川市| 榆林市| 玉溪市| 芦山县| 罗平县| 池州市| 玛曲县| 通海县| 阿巴嘎旗| 新乐市| 洪洞县| 柯坪县| 泾源县| 贵州省| 城口县| 汉寿县| 舞钢市| 河池市| 克什克腾旗| 湘乡市| 平定县| 姜堰市| 黄石市| 防城港市|