成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python中令人頭疼的變量作用域問(wèn)題,終于弄清楚了

開發(fā) 后端
學(xué)習(xí)Python變量過(guò)程中,曾經(jīng)為變量混亂的作用域問(wèn)題頭疼不已,全局變量、局部變量、自由變量傻傻分不清,今天來(lái)跟大家分享 Python變量作用域 的知識(shí)點(diǎn)。

 我們經(jīng)常聽說(shuō)Python函數(shù)訪問(wèn)局部變量、全局變量;在定義裝飾器的時(shí)候,還會(huì)使用自由變量。這些不同的變量是如何賦值、初始化、查找及修改的呢?各自的作用細(xì)則又是什么樣的呢?本篇嘗試解答這個(gè)問(wèn)題。

[[398262]]

Python中的變量名可以指代變量、函數(shù)、類、對(duì)象等。一般來(lái)說(shuō),每個(gè)對(duì)象都有一個(gè)變量名指向,更準(zhǔn)確說(shuō)是 綁定。

作用域的必要性

為啥變量要有作用域呢?

我們?cè)赑ython里遇到的內(nèi)置、局部、全局及自由變量,就是說(shuō)變量的作用域。

語(yǔ)言區(qū)分作用域,是為了復(fù)用變量名。引入作用域,相當(dāng)于給變量劃分了各自的“隔離區(qū)”,在不同”隔離區(qū)“里,查找變量變得很容易。

正是因?yàn)橛辛俗饔糜颍覀冊(cè)诤瘮?shù)內(nèi)才可以隨意使用變量名,而不擔(dān)心其與全局變量、其他函數(shù)中的變量沖突——因?yàn)檫@兩個(gè)作用域是分割的。

BASIC語(yǔ)言只有全局變量,你能想象嗎?你在一個(gè)函數(shù)里命名的循環(huán)變量i,很可能跟全局變量沖突。寫起程序來(lái),舉步維艱。且會(huì)導(dǎo)致很多修改、檢索問(wèn)題,維護(hù)很困難。

Python變量定義的時(shí)間和空間

Python 有哪些作用域呢?

Python是動(dòng)態(tài)類型語(yǔ)言,變量是在定義的時(shí)候賦值的。這句話的意思我們分以下幾個(gè)方面來(lái)理解:

  • a = 1 賦值時(shí)定義變量
  • from tools import cubie 導(dǎo)入時(shí)定義變量 cubie
  • def fun():pass 定義函數(shù),綁定變量fun
  • def fun(name=None):pass 定義變量name為函數(shù)fun的形式變量(也是局部變量),同時(shí)定義函數(shù),綁定便令fun
  • class Car:pass 定義類,綁定類名Car

以上,我們弄清了變量定義的時(shí)刻,下面來(lái)看變量的作用域,也就是變量的活動(dòng)空間怎么規(guī)定出來(lái)的。

變量作用域取決于其 定義位置。

  • 定義在函數(shù)內(nèi)部的變量、定義在函數(shù)聲明中的形式參數(shù),視為局部變量。
  • 定義在 .py 文件內(nèi)的,且函數(shù)、類之外的變量,視為全局變量。
  • 定義在函數(shù)中,嵌套函數(shù)外,且被嵌套函數(shù)引用的變量,視為自由變量。
  • 定義在builtin中的變量,視為內(nèi)置變量。

面對(duì)如此復(fù)雜的四種變量作用域,用一個(gè)例子來(lái)說(shuō)明它們的訪問(wèn)規(guī)則。

LEGB規(guī)則

四個(gè)作用域遵循LEGB規(guī)則,讓我們用一個(gè)例子來(lái)說(shuō)明。

 

  1. import builtins 
  2.  
  3. builtins.b = 'builtins' 
  4. g = 'global' 
  5.  
  6. def outer(o1,o2='o2'): 
  7.     e = 'enclose' 
  8.     def inner(i1,i2='i2'): 
  9.         print(i1,i2,o1,o2,e,g,b) 
  10.     return inner  
  11.  
  12. fun = outer('o1')  
  13. fun('i1'

其輸出為 i1 i2 o1 o2 enclose global builtins

可見,在outer函數(shù)的嵌套函數(shù)inner中的輸出語(yǔ)句 print(i1,i2,o1,o2,e,g,b) 是本程序的重點(diǎn)。其具體執(zhí)行情況如下:

  • print i1和i2,毫無(wú)疑問(wèn)的局部變量。
  • print o1和o2,本地作用域沒有,向上查找到outer函數(shù)形參。形參也為局部變量,所以該變量實(shí)際定義在outer函數(shù)內(nèi),inner這個(gè)內(nèi)嵌函數(shù)外,而inner內(nèi)部引用了這個(gè)變量,所以視為自由變量。
  • print e,本地作用域沒有,類似上例,視為自由變量。
  • print g,本地作用域沒有,自由變量作用域(閉包)沒有,一直上溯到全局作用局找到。
  • print b,本地作用域沒有,自由變量作用域(閉包)沒有,全局作用局沒有,一致上溯到內(nèi)置變量空間找到。

至此,LEGB規(guī)則呼之欲出:在本地空間尋找不到的變量,逐級(jí)向上級(jí)尋找。這里的LEGB分別指代Local,Enclose,Global和Builtin。

在函數(shù)中讀取和賦值全局變量,在內(nèi)嵌函數(shù)中讀取和賦值自由變量,會(huì)有一些不同的地方。

nonlocal 和 global

對(duì)變量名的賦值和引用,是兩種不同的情況:

  • 賦值:創(chuàng)建一個(gè)變量或者修改。
  • 引用:檢索其值。

以上兩者的差別,會(huì)導(dǎo)致我們?cè)诤瘮?shù)中:

  • 賦值一個(gè)
  1. 全局變量:等于創(chuàng)建一個(gè)局部變量。
  2. 自由變量:等于創(chuàng)建一個(gè)局部變量。
  • 引用:正常檢索其值。

我們修改上例中的inner函數(shù)為如下形式:

 

  1. def inner(i1,i2='i2'): 
  2.     e = 'enclose' 
  3.     g = 'inner global' 
  4.     print(i1,i2,o1,o2,e,g,b) 

在嵌套函數(shù)內(nèi),重新定義了g變量,其他語(yǔ)言一般理解這是重新賦值全局變量。但是我們看上條規(guī)則:在函數(shù)中,賦值一個(gè)全局變量時(shí),等于創(chuàng)建一個(gè)局部變量。就是說(shuō)此時(shí)的g已經(jīng)是局部變量了——在程序最后的 print(g) 語(yǔ)句輸出 global,而不是修改后的 inner global 也驗(yàn)證了以上規(guī)則。

完整代碼如下:

 

  1. import builtins 
  2.  
  3. builtins.b = 'builtins' 
  4. g = 'global' 
  5.  
  6. def outer(o1,o2='o2'): 
  7.     e = 'enclose' 
  8.     g = 'inner global' 
  9.     def inner(i1,i2='i2'): 
  10.         print(i1,i2,o1,o2,e,g,b) 
  11.     return inner  
  12.  
  13. fun = outer('o1')  
  14. fun('i1'
  15.  
  16. print(g) 

輸出結(jié)果如下:

 

  1. i1 i2 o1 o2 enclose inner global builtins 
  2. global 

不重新賦值,只是使用全局變量和自由變量,則沒有問(wèn)題。

自由變量也是類似的情況。

為了解決局部作用域中賦值全局變量和自由變量導(dǎo)致的變成局部變量問(wèn)題,Python引入關(guān)鍵字 global 和 nonlocal 。

 

  1. def inner(i1,i2='i2'): 
  2.     global g 
  3.     nonlocal e 
  4.     g = 'inner global' 
  5.     e = 'inner enclose' 

此時(shí)的賦值,則分別是對(duì)全局變量和自由變量的操作,而非新建局部變量。

完整代碼如下:

 

  1. import builtins 
  2.  
  3. builtins.b = 'builtins' 
  4. g = 'global' 
  5.  
  6. def outer(o1,o2='o2'): 
  7.     e = 'enclose' 
  8.     def inner(i1,i2='i2'): 
  9.         global g 
  10.         nonlocal e 
  11.         g = 'inner global' 
  12.         e = 'inner enclose' 
  13.         print(i1,i2,o1,o2,e,g,b) 
  14.     return inner  
  15.  
  16. fun = outer('o1')  
  17. fun('i1'
  18.  
  19. print(g) 

輸出結(jié)果如下:

 

  1. i1 i2 o1 o2 inner enclose inner global builtins 
  2. inner global 

總結(jié)

  • Python的作用域分為四種,分別是局部、全局、自由和內(nèi)置;
  • 定義變量的位置決定了變量的作用域;
  • 作用域的查找遵守LEGB規(guī)則;
  • 為了在局部作用域中修改全局變量和自由變量,引入了 global 關(guān)鍵字和 nonlocal 關(guān)鍵字。

 

責(zé)任編輯:華軒 來(lái)源: Python數(shù)據(jù)之道
相關(guān)推薦

2017-10-20 12:00:36

Python全局解釋器鎖GIL

2017-03-31 15:30:09

2020-02-18 16:48:48

大腦CPU包裝

2023-04-19 09:05:44

2020-11-17 08:32:22

存儲(chǔ)器鏈接

2010-04-08 13:17:39

IT管理系統(tǒng)遷移賽門鐵克

2022-04-07 08:37:05

鏈表技巧單鏈表

2012-05-28 10:06:05

項(xiàng)目開發(fā)項(xiàng)目管理開發(fā)

2017-07-14 14:52:25

MySQLAborted告警案例分析

2021-03-11 15:49:44

人工智能深度學(xué)習(xí)

2022-05-30 08:05:11

架構(gòu)

2021-03-19 14:12:24

2010-11-16 09:07:32

2024-01-12 08:26:16

Linux磁盤文件系統(tǒng)

2022-05-19 12:14:22

分布式開發(fā)框架

2017-09-26 10:36:52

云端部署內(nèi)部

2022-03-11 07:59:09

容器代碼元素

2018-10-25 09:26:07

VLANVXLAN網(wǎng)絡(luò)

2017-10-28 23:00:52

多云混合云云計(jì)算

2019-07-03 15:01:30

戴爾
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧洲一区视频 | 国产精品波多野结衣 | 久久国产精品99久久久大便 | 国产一区二区在线播放 | 久久精点视频 | 美女久久 | 国产日产精品一区二区三区四区 | 欧美日韩国产一区二区三区 | 亚洲精品电影在线观看 | 精品日韩一区 | 欧美乱码精品一区二区三区 | 一区二区三区免费 | 国产精彩视频在线观看 | 免费毛片网站 | 久久久久久看片 | 欧美日韩一二区 | 7799精品视频天天看 | 97人澡人人添人人爽欧美 | 亚洲国产精品视频一区 | 蜜桃日韩 | 亚洲情综合五月天 | 亚洲毛片在线 | 日韩精品一区二区三区久久 | 久久精品 | 日本精品久久久久久久 | 日韩精品中文字幕一区二区三区 | 一级毛片中国 | 成人精品一区亚洲午夜久久久 | 黄色片大全在线观看 | 三级成人在线 | 特级特黄特色的免费大片 | 久久网站免费视频 | 国产福利资源 | 成人免费视频在线观看 | 在线观看 亚洲 | 97久久精品午夜一区二区 | 国产午夜精品福利 | 国产精品无码专区在线观看 | 成人在线免费观看 | 美美女高清毛片视频免费观看 | 一区二区不卡视频 |