類使用類方法,訪問 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 ?
當內部作用域想修改外部作用域的變量時,就要用到 global,
如果只是訪問的話,可以不用加。
可以考慮用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())
當遇到一個名字的時候,是從當前開始向外找的。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,
- ......