Python函数全局变量?

我知道我应该首先避免使用全局变量,因为像这样的混乱,但如果我要使用它们,下面是一个有效的方式去使用它们吗?(我正在尝试调用在单独函数中创建的变量的全局副本。)

x = "somevalue"


def func_A ():
global x
# Do things to x
return x


def func_B():
x = func_A()
# Do things
return x


func_A()
func_B()

第二个函数使用的x是否具有与func_a使用和修改的x的全局副本相同的值?在定义之后调用函数时,顺序重要吗?

769133 次浏览

如果你只是想访问一个全局变量,你只需要使用它的名字。然而,为了改变的值,你需要使用global关键字。

如。

global someVar
someVar = 55

这将把全局变量的值更改为55。否则它只会把55赋值给一个局部变量。

函数定义清单的顺序并不重要(假设它们不以某种方式相互引用),调用它们的顺序才重要。

当你想改变赋给全局变量的值时,你必须使用global声明。

你不需要它来读取全局变量。注意,调用对象上的方法(即使它改变了该对象中的数据)不会改变持有该对象的变量的值(没有反射魔法)。

正如其他人所注意到的,当你希望函数能够修改全局变量时,你需要在函数中声明变量global。如果你只想访问它,那么你不需要global

更详细地说,“modify”的意思是:如果你想re-bind全局名称,使它指向一个不同的对象,该名称必须在函数中声明为global

许多修改(突变)对象的操作重新绑定全局名称以指向不同的对象,因此它们是所有有效,而没有在函数中声明名称global

d = {}
l = []
o = type("object", (object,), {})()


def valid():     # these are all valid without declaring any names global!
d[0] = 1      # changes what's in d, but d still points to the same object
d[0] += 1     # ditto
d.clear()     # ditto! d is now empty but it`s still the same object!
l.append(0)   # l is still the same list but has an additional member
o.test = 1    # creating new attribute on o, but o is still the same object

在Python作用域中,对尚未在该作用域中声明的变量的任何赋值都会创建一个新的局部变量除非,该变量在前面的函数中声明为引用全局作用域变量,使用关键字global

让我们看看伪代码的修改版本,看看会发生什么:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'


def func_A():
# The below declaration lets the function know that we
#  mean the global 'x' when we refer to that variable, not
#  any local one


global x
x = 'A'
return x


def func_B():
# Here, we are somewhat mislead.  We're actually involving two different
#  variables named 'x'.  One is local to func_B, the other is global.


# By calling func_A(), we do two things: we're reassigning the value
#  of the GLOBAL x as part of func_A, and then taking that same value
#  since it's returned by func_A, and assigning it to a LOCAL variable
#  named 'x'.
x = func_A() # look at this as: x_local = func_A()


# Here, we're assigning the value of 'B' to the LOCAL x.
x = 'B' # look at this as: x_local = 'B'


return x # look at this as: return x_local

事实上,你可以用名为x_local的变量重写所有func_B,它的工作原理是一样的。

顺序只与函数执行改变全局x值的操作的顺序有关。因此,在我们的例子中,顺序并不重要,因为func_B调用func_A。在这个例子中,顺序很重要:

def a():
global foo
foo = 'A'


def b():
global foo
foo = 'B'


b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.
注意,global只需要修改全局对象。你仍然可以在函数中访问它们而不声明global。 因此,我们有:

x = 5


def access_only():
return x
# This returns whatever the global value of 'x' is


def modify():
global x
x = 'modified'
return x
# This function makes the global 'x' equal to 'modified', and then returns that value


def create_locally():
x = 'local!'
return x
# This function creates a new local variable named 'x', and sets it as 'local',
#  and returns that.  The global 'x' is untouched.

注意create_locallyaccess_only之间的区别——access_only访问全局x,尽管没有调用global,而且即使create_locally也不使用global,它创建了一个本地副本,因为它是分配值。

这里的困惑是为什么不应该使用全局变量。

这里有一个例子让我发现,使用全局变量作为参数的默认值。

globVar = None    # initialize value of global variable


def func(param = globVar):   # use globVar as default value for param
print 'param =', param, 'globVar =', globVar  # display values


def test():
global globVar
globVar = 42  # change value of global
func()


test()
=========
output: param = None, globVar = 42

我期望param的值为42。惊喜。Python 2.7在第一次解析函数func时计算globVar的值。改变globVar的值并不影响分配给param的默认值。延迟评估,如下所示,正如我所需要的那样。

def func(param = eval('globVar')):       # this seems to work
print 'param =', param, 'globVar =', globVar  # display values

或者,如果你想安全起见,

def func(param = None)):
if param == None:
param = globVar
print 'param =', param, 'globVar =', globVar  # display values

您可以直接访问函数中的全局变量。如果你想改变全局变量的值,使用"global variable_name"。示例如下:

var = 1
def global_var_change():
global var
var = "value changed"
global_var_change() #call the function for changes
print var

一般来说,这不是一个好的编程实践。通过破坏名称空间逻辑,代码可能变得难以理解和调试。