91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python中的global關鍵字

發布時間:2020-07-20 19:52:04 來源:網絡 閱讀:760 作者:nineteens 欄目:編程語言

  摘要

  global 標志實際上是為了提示 python 解釋器,表明被其修飾的變量是全局變量。這樣解釋器就可以從當前空間 (current scope) 中讀寫相應變量了。

  Python 的全局變量是模塊 (module) 級別的

  每個 python 函數擁有對應的 __globals__ 字典,該字典與函數所屬模塊的 __dict__ 字典完全相同。函數的全局變量也會從這個字典中獲取

  注:上面三句話的意思就是,python 解釋器發現函數中的某個變量被 global 關鍵字修飾,就去函數的 __globals__ 字典變量中尋找(因為 python 中函數也是一等對象);同時,一個模塊中每個函數的 __globals__ 字典變量都是模塊 __dict__ 字典變量的引用,二者值完全相同。

  避免全局變量將使得程序更容易被調試,同時也能提升程序的可讀性

  使用到的全局變量只是作為引用,不在函數中修改它的值的話,不需要加global關鍵字. 使用到的全局變量,需要在函數中修改的話,就涉及到歧義問題. 因此在函數中修改全局變量的話需要加global關鍵字

  動機

  我最近遇到了一個關于 python 全局變量的問題,如下面這個簡單例子里展示(當然實際代碼要比這個復雜的多,這里只是一個抽象出來當例子)。例子中 foo.py 定義了函數 f,而函數 f 調用了全局變量 a:

  # foo.py

  def f():

  print(a)

  def main():

  global a

  a = 5

  f()

  if __name__ == '__main__':

  main()

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

  # bar.py

  from foo import f

  def main():

  f()

  main()

  運行 bar.py 將報 NameError 錯誤。這是因為 a 被定義在 foo.py 的 main 函數中,而當導入 f 函數時, foo.py 的 main 函數并未被運行,所以 a 也沒喲被定義。

  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

  為了修復上面當問題第一反應是在 bar.py 中定義全局變量 a,這樣 f 就可以找到變量 a 了,如下面的代碼:

  # bar.py

  from foo import f

  def main():

  global a

  a = 4

  f()

  main()

  然而依舊會報錯,黑人問號臉???

  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

  函數的 __globals__ 屬性與 python 的 global 語句

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

  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 被認為是全局變量。Python 中的每一個函數都擁有一個 __globals__ 字典變量,該變量實際是函數所屬模塊的 __dict__ 變量的引用。所以在 bar.py 中我們想在 bar.main 函數中將全局變量 a 賦值為4,實際改變的是 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,然而這個值對函數 f 來說確是不可見的,因為 f.__globals__ 實際等于 foo.__dict__ (簡單而言就是命名空間不同)

  from foo import f

  print(f.__globals__)

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

  # foo.py無錫婦科檢查醫院 http://www.87554006.com/

  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()

  運行 bar.py 輸出3,而不是 4。

  修改函數全局變量的值:更新 globals

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

  # bar.py

  from foo import f

  def main():

  f.__globals__['a'] = 4

  f()

  main()

  模塊的 dict 變量和猴子布丁 (monkey-patching)

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

  # bar.py

  import foo

  from foo import f

  def main():

  foo.a = 4

  f()

  如果你曾經使用過運行中給代碼打補丁的庫,一般就是這么實現的。直接修改被打補丁的模塊的 __dict__ 中特定的對象或函數。、

  輸入使得函數變得更加容易測試

  上面的例子中的函數 f 如果接受輸入變量的話,而不是使用全局變量,代碼將更容易被測試。同時可讀性也更好,出了問題也更容易 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)


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广昌县| 监利县| 游戏| 马尔康县| 双流县| 大埔县| 阿荣旗| 漾濞| 澄迈县| 衡阳县| 湟中县| 茂名市| 藁城市| 萍乡市| 鄯善县| 通化县| 城口县| 冕宁县| 皮山县| 巩留县| 汪清县| 鞍山市| 图们市| 天台县| 体育| 青海省| 巴中市| 巫溪县| 武隆县| 辽中县| 东台市| 望都县| 遵义市| 遂川县| 区。| 聊城市| 乐都县| 福州市| 龙陵县| 科尔| 青阳县|