程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python 使用全局變量,為什麼有的時候可以不加 global ?

編輯:Python

類使用類方法,訪問 success_list 是可以的!

from loguru import logger
success_list: list[float] = [1,2,3,4,5,6,7,8]
class Myclass:
def run(self):
logger.debug(success_list)
Myclass().run()
logger.debug(success_list)

運行結果:

2022-07-29 16:15:23.838 | DEBUG | __main__:run:8 - [1, 2, 3, 4, 5, 6, 7, 8]
2022-07-29 16:15:23.838 | DEBUG | __main__:<module>:13 - [1, 2, 3, 4, 5, 6, 7, 8]

但是加兩行代碼就不行了

from loguru import logger
success_list: list[float] = [1,2,3,4,5,6,7,8]
class Myclass:
def run(self):
logger.debug(success_list)
success_list = success_list[1:]
logger.debug(success_list)
Myclass().run()
logger.debug(success_list)

運行結果:

Traceback (most recent call last):
File "/Users/ponponon/Desktop/code/me/ideaboom/tools copy.py", line 12, in <module>
Myclass().run()
File "/Users/ponponon/Desktop/code/me/ideaboom/tools copy.py", line 8, in run
logger.debug(success_list)
UnboundLocalError: local variable 'success_list' referenced before assignment
主注意,報錯在 logger.debug(success_list) 而不是 success_list = success_list[1:]

但是加上 global 又可以了!?

from loguru import logger
success_list: list[float] = [1,2,3,4,5,6,7,8]
class Myclass:
def run(self):
global success_list
logger.debug(success_list)
success_list = success_list[1:]
logger.debug(success_list)
Myclass().run()
logger.debug(success_list)

運行結果:

2022-07-29 16:16:33.181 | DEBUG | __main__:run:9 - [1, 2, 3, 4, 5, 6, 7, 8]
2022-07-29 16:16:33.181 | DEBUG | __main__:run:11 - [2, 3, 4, 5, 6, 7, 8]
2022-07-29 16:16:33.181 | DEBUG | __main__:<module>:15 - [2, 3, 4, 5, 6, 7, 8]

為什麼第一份代碼可以不加 global ?



其他答案1:

當內部作用域想修改外部作用域的變量時,就要用到 global,
如果只是訪問的話,可以不用加。


其他答案2:

可以考慮用inspect.getclosurevars方法來看一下python對兩個函數處理方式的區別。

下面用一個簡單的例子連同執行結果說明一下:

>>> import inspect
>>> g = 1
>>> def a():
...  return g
...
>>> def b():
...  g = g + 1
...  return g
...
>>> inspect.getclosurevars(a)
ClosureVars(nonlocals={}, globals={'g': 1}, builtins={}, unbound=set())
>>> inspect.getclosurevars(b)
ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())

其他答案3:

當遇到一個名字的時候,是從當前開始向外找的。success_lines = .... 是一個 name binding operation ,相當於它會在當前層創建一個 success_lines;這樣,如果沒有 global ,就找不到外層的了,想用全局的就必須 global 。但是如果沒有賦值,那麼當前沒有這個變量,就可以找到外層的。


resolution of names

4.2.2. Resolution of names
......
When a name is used in a code block, it is resolved using the nearest enclosing scope.
......
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block.
.....
If the global statement occurs within a block, all uses of the names specified in the statement refer to the bindings of those names in the top-level namespace.

binding of names

Names refer to objects. Names are introduced by name binding operations.

The following constructs bind names:

  • formal parameters to functions,
  • class definitions,
  • function definitions,
  • assignment expressions,
  • ......

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved