亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

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

系統(tǒng) 2144 0

摘要

  • 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)?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 
            
              
  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 
            
              
  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)?f.__globals__?實(shí)際等于?foo.__dict__?(簡(jiǎn)單而言就是命名空間不同)

            
from foo import f
print(f.__globals__)

          

假設(shè)我們?cè)?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í)有所幫助,也希望大家多多支持腳本之家。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产精品九九九久久九九 | 第一福利视频 | 国产一级特黄aa级特黄裸毛片 | 日韩一区精品视频在线看 | 国产精品久久久久无码av | 午夜a毛片 | 国产精品一区二区久久精品 | 久久经典| 亚洲在线视频免费 | 97视频免费在线观看 | 亚洲国产欧洲综合997久久 | 国产免费久久精品 | 97婷婷狠狠成人免费视频 | 四虎永久在线精品 | 国产精品久久亚洲不卡动漫 | 亚洲毛片视频 | 国产精品午夜性视频 | 国产成人精品cao在线 | 国产福利观看 | 韩国网站爱久久 | 国产欧美日韩亚洲精品区2345 | 亚洲天天在线日亚洲洲精 | 情趣色视频网站 | 91热视频在线 | 综合7799亚洲伊人爱爱网 | 成人在激情在线视频 | 亚洲欧洲一区二区三区久久 | 啪啪综合网 | 四虎在线看 | 激情浪荡yin乱之合集 | 四虎影视884a精品国产四虎 | 精品久久久久久亚洲精品 | h在线免费视频 | 久久国产精品免费 | 四虎影视永久免费视频观看 | 色www国产阿娇 | 热99re国产久热在线 | 99玖玖| 久热久草 | 日韩中文字幕免费观看 | 狠狠色成人综合网图片区 |