全局变量:赋值与方法

2024-04-25 13:30:45 发布

您现在位置:Python中文网/ 问答频道 /正文

为了避免意外修改全局变量,python需要一个显式的global语句,然后再赋给全局变量。但是,通过调用全局变量的方法来修改全局变量不需要任何额外的语句:

x = [1, 2]
y = [1, 2]
def f():
  global x
  x = x + [3] # won't affect global variable without global statement
  y.append(3) # will affect global variable without global statement

这似乎有点不一致。做出这种设计选择是因为通过方法调用修改全局可变对象比用一个全新的对象替换它们更不危险/更不糟糕吗?如果是,为什么?你知道吗


Tags: 对象方法def语句全局variableglobalwill
3条回答

一句话:

“如果不显式声明,python将不允许您更改全局变量的reference”。你知道吗

现在让我们来解释一下刚才读到的内容,将对象赋值给变量实际上是生成一个reference,它是一个内存地址,指向对象在内存中的位置。你知道吗

当我们写:

x = [1, 2]

实际上,在内存的某个地方,list对象被分配了它的所有函数引用、成员和其他垃圾。这个地址实际上保存在x。你知道吗

我们可以使用函数id(object)来注意变化:

x = [1, 2]
def foo():
 print id(x)    # an address like 50075016
 y = [1, 2, 3]
 print id(y)    # another address like 50075272 
 x = y          # won't work without declaring 'global x' 
                # because we try to change the address stored in x
                # from 50075016 to 50075272.
 x.append(3)    # works
 print id(x)    # same address 50075016

它实际上不是关于值级别上的可变性,这是您如何看待它的;它是关于变量引用的可变性,即命名项(变量)指向什么。你知道吗

x = [1, 2]
print(id(x)) # 57226944
y = [1, 2]
print(id(y)) # 57262728
def f():
  global x
  x = x + [3]
  print(id(x)) # 57306648 - CHANGED
  y.append(3)
  print(id(y)) # 57262728 - UNCHANGED

f()

请注意,名称“x”现在指向一个新对象(新创建的列表),而对y的.append操作没有更改名称“y”指向的对象。你知道吗

documentation

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.

在您的例子中,y是在函数内部引用的,因此是隐式全局的。另一方面,x被赋予一个值,因此它必须是本地的,除非另有明确声明。你知道吗

文档进一步回答了您的问题:

Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring global for assigned variables provides a bar against unintended side-effects. On the other hand, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.

相关问题 更多 >