2012-05-14 322 views
176

我知道我应该首先避免使用全局变量,因为这样的混淆,但如果我要使用它们,下面是使用它们的有效方法吗? (我想打电话给一个单独的函数创建一个变量的全球复印件)。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第二函数使用有xfunc_a使用和修改全局复制相同的值?定义后调用函数时,命令是否重要?

+0

还要小心,不要因为你的函数中分配了一个变量而认为python会在赋值之前对待引用。在第一次分配之前,如果你使用x,它不会是全局的,或者是本地的。你会在你的脸上得到臭名昭着的UnboundLocalError异常:) – osirisgothra

回答

267

如果你想简单地访问一个全局变量,你只需要使用它的名字。然而要更改其值你需要使用global关键字。

E.g.

global someVar 
someVar = 55 

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

的函数定义列表无关紧要(假设他们没有提及对方以某种方式)的顺序,他们被称为顺序一样。

+2

在我给出的代码中,func_B将事物(1)全局复制到x(从func_A获得),(2)到一个局部变量x func_A的结果相同的值,或者(3)与没有值和(在编译器眼中)与局部变量x没有关系的“某个值”或func_A中的x? –

+0

'func_B'中的'x'是一个局部变量,它从调用返回值'func_A'获取它的值 - 所以我想这会使它成为你的(2) – Levon

+0

ok,假设x是随机序列由func_A生成的某种类型(即func_A每次运行时都会生成一个不同的x)。运行程序时会如何写func_b修改与调用func_a时最初生成的x不同的x?如果是这样,我该如何解决它? –

0

当你想改变分配到一个全局变量的值必须使用global声明。

你不需要它从一个全局变量读取。请注意,在对象上调用方法(即使它改变了该对象中的数据)并不会改变保存该对象的变量的值(缺少反射魔法)。

+2

这种措辞是不幸的。在Python中,分配给变量的值是一个引用,所以它在技术上是正确的(我毫不怀疑你的意思),但是很多读者可能会将“改变值”解释为“改变对象”,而不是案例 - 'xs.append(xs.pop(0))'工作得很好,没有'全局xs'。 – delnan

+0

@delnan我的回答措辞谨慎,但我会澄清。 – Marcin

12

正如其他人所指出的,你需要在一个函数来声明一个变量global当你想要的功能,能够修改全局变量。如果你只想访问它,那么你不需要global

要进入上更详细一点,什么是“修改”的意思是:如果你想重新绑定全局名称,使其指向一个不同的对象,该名称必须在声明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 
65

在一个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之间的区别 - 尽管没有要求globalaccess_only正在访问全局X,即使create_locally不使用global或者,它会创建一个本地副本,因为它的分配一个值。

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

+0

我不认为这是在实践中很混乱,你只需要了解[python的范围规则](http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules)。 – Darthfett

2

下面是一个案例,使用全局值作为参数的默认值。

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 

我曾预计参数值为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 
0

您可以直接在函数内部访问一个全局变量。如果要更改该全局变量的值,请使用“全局变量名称”。看下面的例子:

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

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