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

python中的global關(guān)鍵字的使用方法

 更新時(shí)間:2019年08月20日 14:12:52   作者:隨機(jī)漫步_  
這篇文章主要介紹了python中的global關(guān)鍵字的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

摘要

  • global 標(biāo)志實(shí)際上是為了提示 python 解釋器,表明被其修飾的變量是全局變量。這樣解釋器就可以從當(dāng)前空間 (current scope) 中讀寫(xiě)相應(yīng)變量了。
  • Python 的全局變量是模塊 (module) 級(jí)別的
  • 每個(gè) python 函數(shù)擁有對(duì)應(yīng)的 __globals__ 字典,該字典與函數(shù)所屬模塊的 __dict__ 字典完全相同。函數(shù)的全局變量也會(huì)從這個(gè)字典中獲取
  • 注:上面三句話的意思就是,python 解釋器發(fā)現(xiàn)函數(shù)中的某個(gè)變量被 global 關(guān)鍵字修飾,就去函數(shù)的 __globals__ 字典變量中尋找(因?yàn)?python 中函數(shù)也是一等對(duì)象);同時(shí),一個(gè)模塊中每個(gè)函數(shù)的 __globals__ 字典變量都是模塊 __dict__ 字典變量的引用,二者值完全相同。
  • 避免全局變量將使得程序更容易被調(diào)試,同時(shí)也能提升程序的可讀性
  • 使用到的全局變量只是作為引用,不在函數(shù)中修改它的值的話,不需要加global關(guān)鍵字. 使用到的全局變量,需要在函數(shù)中修改的話,就涉及到歧義問(wèn)題. 因此在函數(shù)中修改全局變量的話需要加global關(guān)鍵字

動(dòng)機(jī)

我最近遇到了一個(gè)關(guān)于 python 全局變量的問(wèn)題,如下面這個(gè)簡(jiǎn)單例子里展示(當(dāng)然實(shí)際代碼要比這個(gè)復(fù)雜的多,這里只是一個(gè)抽象出來(lái)當(dāng)例子)。例子中 foo.py 定義了函數(shù) f,而函數(shù) f 調(diào)用了全局變量 a:

# foo.py
 
def f():
  print(a)
 
def main():
  global a
  a = 5
  f()
 
if __name__ == '__main__':
  main()

運(yùn)行上面這個(gè)文件將如預(yù)料中的輸出5。在另一個(gè)文件 bar.py 中我們引入上面的 f,代碼如下

# bar.py
from foo import f
 
def main():
  f()
 
main()

運(yùn)行 bar.py 將報(bào) NameError 錯(cuò)誤。這是因?yàn)?nbsp;a 被定義在 foo.py 的 main 函數(shù)中,而當(dāng)導(dǎo)入 f 函數(shù)時(shí), foo.py 的 main 函數(shù)并未被運(yùn)行,所以 a 也沒(méi)喲被定義。

Traceback (most recent call last):
 File "bar.py", line 10, in <module>
  main()
 File "bar.py", line 7, in main
  f()
 File "foo.py", line 5, in f
  print(a)
NameError: global name 'a' is not defined

定義全局變量 a

為了修復(fù)上面當(dāng)問(wèn)題第一反應(yīng)是在 bar.py 中定義全局變量 a,這樣 f 就可以找到變量 a 了,如下面的代碼:

# bar.py
from foo import f
 
def main():
  global a
  a = 4
  f()
 
main()

然而依舊會(huì)報(bào)錯(cuò),黑人問(wèn)號(hào)臉???

Traceback (most recent call last):
 File "/tmp/example/bar.py", line 13, in <module>
  main()
 File "/tmp/example/bar.py", line 9, in main
  f()
 File "/tmp/example/foo.py", line 5, in f
  print(a)
NameError: global name 'a' is not defined

函數(shù)的 __globals__ 屬性與 python 的 global 語(yǔ)句

python 的 global 語(yǔ)句的作用只是提示 python 解釋器,被 global 修飾的變量是一個(gè)全局變量,利用上面例子里函數(shù) f 的反編譯代碼可以清除的看到這一點(diǎn):

import dis
from foo import f
 
dis.dis(f)
5      0 LOAD_GLOBAL       0 (print)
      2 LOAD_GLOBAL       1 (a)
      4 CALL_FUNCTION      1
      6 POP_TOP
      8 LOAD_CONST        0 (None)
      10 RETURN_VALUE

面可以看出變量 a 被認(rèn)為是全局變量。Python 中的每一個(gè)函數(shù)都擁有一個(gè) __globals__ 字典變量,該變量實(shí)際是函數(shù)所屬模塊的 __dict__ 變量的引用。所以在 bar.py 中我們想在 bar.main 函數(shù)中將全局變量 a 賦值為4,實(shí)際改變的是 bar.py 的 __dict__ 字典變量 (注:而不是定義 f 的 foo.py 的 __dict__ 字典變量)

# bar.py
def main():
  global a
  a = 4
  print(main.__globals__.keys())
  print(main.__globals__['a'])
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'foo', 'f', 'dis', 'main', 'a'])
4

上面的代碼輸出了 main.__globals__ (即 bar.__dict__ ) 中全局變量 a 的值是4,然而這個(gè)值對(duì)函數(shù) f 來(lái)說(shuō)確是不可見(jiàn)的,因?yàn)?nbsp;f.__globals__ 實(shí)際等于 foo.__dict__ (簡(jiǎn)單而言就是命名空間不同)

from foo import f
print(f.__globals__)

假設(shè)我們?cè)?nbsp;foo.py 所有函數(shù)的外部預(yù)先定義了全局變量 a ,那么在將函數(shù) f 導(dǎo)入時(shí),a 會(huì)隨著 f.__globals__ 一同被導(dǎo)入。但這時(shí)被導(dǎo)入的 f.__globals__["a"] ( 即 foo.__dict__["a"] ) 和 bar.main 中賦值的 bar.main.__globals__["a"] ( 即 bar.__dict__["a"] ) 仍然不是同一個(gè)變量,即賦值無(wú)法改變函數(shù) f 的輸出,如下面的例子所示。

# foo.py
a = 3
 
def f():
  print(a)
 
def main():
  global a
  a = 5
  f()
 
if __name__ == '__main__':
  main()
# bar.py
from foo import f
 
def main():
  global a
  a = 4
  f()
 
main()

運(yùn)行 bar.py 輸出3,而不是 4。

修改函數(shù)全局變量的值:更新 globals

就上述例子而言,如果我們想在 bar.py 中改變函數(shù) f 的輸出,則需要直接更新其 __globals__ 變量的值。

# bar.py
from foo import f
 
def main():
  f.__globals__['a'] = 4
  f()
 
main()
  • 模塊的 dict 變量和猴子布丁 (monkey-patching)

如上所述,函數(shù)的 __globals__ 變量實(shí)際是其所屬模塊 __dict__ 變量的引用。所以為了達(dá)到上面修改全局變量的目的,也可以直接更新 foo.__dict__ 。修改模塊 foo 的屬性 (attribute) 值即可直接更新 foo.__dict__ 。

# bar.py
import foo
from foo import f
 
 
def main():
  foo.a = 4
  f()

如果你曾經(jīng)使用過(guò)運(yùn)行中給代碼打補(bǔ)丁的庫(kù),一般就是這么實(shí)現(xiàn)的。直接修改被打補(bǔ)丁的模塊的 __dict__ 中特定的對(duì)象或函數(shù)。、

輸入使得函數(shù)變得更加容易測(cè)試
上面的例子中的函數(shù) f 如果接受輸入變量的話,而不是使用全局變量,代碼將更容易被測(cè)試。同時(shí)可讀性也更好,出了問(wèn)題也更容易 debug。

# foo.py
def f(a):
  print(a)
 
 
def main():
  a = 5
  f(a)
 
if __name__ == '__main__':
  main()
# bar.py
from foo import f
 
def main():
  a = 3
  f(a)

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

相關(guān)文章

  • python處理文本文件并生成指定格式的文件

    python處理文本文件并生成指定格式的文件

    本節(jié)主要介紹了python如何處理文本文件并生成指定格式的文件,需要的朋友可以參考下
    2014-07-07
  • Python利用memory_profiler實(shí)現(xiàn)內(nèi)存分析

    Python利用memory_profiler實(shí)現(xiàn)內(nèi)存分析

    memory_profiler是第三方模塊,用于監(jiān)視進(jìn)程的內(nèi)存消耗以及python程序內(nèi)存消耗的逐行分析。本文將利用memory_profiler實(shí)現(xiàn)內(nèi)存分析,需要的可以參考一下
    2022-10-10
  • 使用python進(jìn)行圖片的文字識(shí)別詳細(xì)代碼

    使用python進(jìn)行圖片的文字識(shí)別詳細(xì)代碼

    Tesseract OCR是一款由Google團(tuán)隊(duì)開(kāi)發(fā)的開(kāi)源OCR引擎,用于將圖片、PDF 等格式中的文本轉(zhuǎn)換為可編輯的文本格式,本文主要介紹了Python進(jìn)行圖片的文字識(shí)別功能OCR的相關(guān)知識(shí),需要的朋友可以參考下
    2023-05-05
  • python安裝與使用redis的方法

    python安裝與使用redis的方法

    這篇文章主要介紹了python安裝與使用redis的方法,分析了安裝與配置的具體步驟,并結(jié)合實(shí)例詳細(xì)分析了redis數(shù)據(jù)庫(kù)的具體使用技巧,需要的朋友可以參考下
    2016-04-04
  • Jupyter加載文件的實(shí)現(xiàn)方法

    Jupyter加載文件的實(shí)現(xiàn)方法

    這篇文章主要介紹了Jupyter加載文件的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • Python中的圖形繪制簡(jiǎn)單動(dòng)畫(huà)實(shí)操

    Python中的圖形繪制簡(jiǎn)單動(dòng)畫(huà)實(shí)操

    這篇文章主要介紹了Python中的圖形繪制簡(jiǎn)單動(dòng)畫(huà)實(shí)操,?Matplotlib?是一個(gè)非常廣泛的庫(kù),它也支持圖形動(dòng)畫(huà),動(dòng)畫(huà)工具以?matplotlib.animation?基類(lèi)為中心,它提供了一個(gè)框架,圍繞該框架構(gòu)建動(dòng)畫(huà),下面來(lái)看看具體的實(shí)現(xiàn)過(guò)程吧,需要的小伙伴可以參考一下
    2022-02-02
  • Python 編碼Basic Auth使用方法簡(jiǎn)單實(shí)例

    Python 編碼Basic Auth使用方法簡(jiǎn)單實(shí)例

    這篇文章主要介紹了 Python 編碼Basic Auth使用方法簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Flask入門(mén)之上傳文件到服務(wù)器的方法示例

    Flask入門(mén)之上傳文件到服務(wù)器的方法示例

    這篇文章主要介紹了Flask入門(mén)之上傳文件到服務(wù)器的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Python操作MySQL的方法詳細(xì)解讀

    Python操作MySQL的方法詳細(xì)解讀

    這篇文章主要介紹了Python操作MySQL的方法詳細(xì)解讀,在Python中,通過(guò)使用第三方庫(kù):pymysql,完成對(duì)MySQL數(shù)據(jù)庫(kù)的操作,Python操作MySQL并不難,難點(diǎn)是如何編寫(xiě)合適的SQL語(yǔ)句,需要的朋友可以參考下
    2023-11-11
  • django緩存配置的幾種方法詳解

    django緩存配置的幾種方法詳解

    緩存對(duì)各位學(xué)習(xí)或者使用django的朋友們來(lái)說(shuō)應(yīng)該都不陌生,下面這篇文章主要給大家介紹了關(guān)于django緩存配置的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07

最新評(píng)論

安化县| 赫章县| 昌乐县| 阿拉善左旗| 西贡区| 亳州市| 承德县| 平顶山市| 九寨沟县| 姜堰市| 保山市| 新竹县| 松阳县| 胶南市| 娄烦县| 隆林| 峨山| 德惠市| 石泉县| 肃宁县| 盐亭县| 海阳市| 南京市| 房产| 黔西县| 夏津县| 区。| 红原县| 二手房| 合阳县| 福安市| 原平市| 龙口市| 台江县| 沙河市| 汕尾市| 叶城县| 鄄城县| 乐山市| 沿河| 夏邑县|