Python 使用全局变量,为什么有的时候可以不加 global ?

Python 使用全局变量,为什么有的时候可以不加 global ?

类使用类方法,访问 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]

但是加两行代码就不行了

python">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,
  • ......

以上是 Python 使用全局变量,为什么有的时候可以不加 global ? 的全部内容, 来源链接: utcz.com/p/938557.html

回到顶部