在函数中使用全局变量

如何在函数中创建或使用全局变量?

如果在一个函数中创建全局变量,如何在另一个函数中使用该全局变量?我是否需要将全局变量存储在需要对其进行访问的函数的局部变量中?

答案

您可以通过声明为使用其他功能的全局变量global指派每个功能吧:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

我想这是因为全局变量是如此危险,Python 希望通过显式要求使用global关键字来确保您真正知道这就是要使用的内容。

如果要在模块之间共享全局变量,请参见其他答案。

如果我正确地理解了您的情况,那么您所看到的是 Python 处理本地(函数)和全局(模块)名称空间的结果。

假设您有一个像这样的模块:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

您可能希望它会显示 42,但是会显示 5。如前所述,如果向func1()添加 ' global ' 声明,则func2()将输出 42。

def func1():
    global myGlobal
    myGlobal = 42

这里发生的事情是,Python 假定在函数内的任何位置分配给的任何名称都是该函数的本地名称,除非另有明确说明。如果仅从名称读取 ,并且该名称在本地不存在,它将尝试在任何包含的范围(例如,模块的全局范围)中查找该名称。

因此,当将 42 分配给名称myGlobal时,Python 将创建一个局部变量,该局部变量myGlobal相同名称的全局变量。该 local 超出范围,并在func1()返回时被垃圾回收 ;同时, func2()只能看到(未修改的)全局名称。请注意,此命名空间决定是在编译时发生的,而不是在运行时发生的 - 如果在分配给func1()之前读取myGlobal的值, myGlobal得到UnboundLocalError ,因为 Python 已经确定必须局部变量,但尚未有任何关联的值。但是通过使用 ' global ' 语句,您告诉 Python 它应该在其他地方查找该名称,而不是在本地分配它。

(我相信这种行为主要是通过优化本地名称空间而产生的 - 如果没有这种行为,Python 的 VM 每次在函数内部分配新名称时都需要至少执行三个名称查找(以确保名称没有 t 已存在于模块 / 内置级别),这将大大减慢非常常见的操作的速度。)

您可能想探索名称空间的概念。在 Python 中, 模块全球数据的天然场所:

每个模块都有自己的专用符号表,模块中定义的所有功能都将其用作全局符号表。因此,模块的作者可以在模块中使用全局变量,而不必担心与用户的全局变量的意外冲突。另一方面,如果您知道自己在做什么,则可以使用与引用modname.itemname功能相同的符号modname.itemname来触摸模块的全局变量。

此处描述了模块中全局变量的特定用法 - 如何在模块之间共享全局变量? ,为了完整起见,这里共享内容:

在单个程序中的模块之间共享信息的规范方法是创建一个特殊的配置模块(通常称为configcfg )。只需将配置模块导入应用程序的所有模块中即可;然后该模块就可以作为全局名称使用。因为每个模块只有一个实例,所以对模块对象所做的任何更改都会在所有地方反映出来。例如:

文件:config.py

x = 0   # Default value of the 'x' configuration setting

档案:mod.py

import config
config.x = 1

档案:main.py

import config
import mod
print config.x

Python 使用一种简单的启发式方法来确定应从本地和全局加载变量的范围。如果变量名称出现在分配的左侧,但未声明为全局变量,则假定它是局部变量。如果它没有出现在作业的左侧,则假定它是全局的。

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>>

请参阅foo()赋值左侧出现的 baz 如何是唯一的LOAD_FAST变量。

如果要在函数中引用全局变量,则可以使用global关键字声明哪些变量是全局变量。您不必在所有情况下都使用它(因为这里的人不正确地声称)- 如果在本地作用域或定义此函数的函数的作用域中找不到表达式中引用的名称,则在全局范围内查找该名称变量。

但是,如果在函数中分配了一个未声明为全局变量的新变量,则该变量将隐式声明为局部变量,并且可能使任何现有的具有相同名称的全局变量都被遮盖。

同样,全局变量是有用的,这与某些 OOP 狂热者相反,特别是对于较小的脚本(OOP 过分杀伤)更是如此。

除了已经存在的答案之外,还要使其更加混乱:

在 Python 中,仅在函数内部引用的变量是隐式全局的 。如果在函数体内的任何位置为变量分配了新值,则假定该变量为local 。如果在函数内部为变量分配了新值,则该变量是隐式局部变量,您需要将其显式声明为 “global”。

尽管起初有些令人惊讶,但片刻的考虑可以解释这一点。一方面,要求全局分配变量可防止意外副作用。另一方面,如果所有全局引用都需要全局,那么您将一直使用全局。您必须将对内置函数或导入模块的组件的每个引用声明为全局引用。这种混乱将破坏全球宣言对确定副作用的有用性。

资料来源: Python 中局部和全局变量的规则是什么?

如果在一个函数中创建全局变量,如何在另一个函数中使用该变量?

我们可以使用以下功能创建一个全局变量:

def create_global_variable():
    global global_variable # must declare it to be a global first
    # modifications are thus reflected on the module's global scope
    global_variable = 'Foo'

编写函数实际上不会运行其代码。因此,我们调用create_global_variable函数:

>>> create_global_variable()

使用全局变量而不进行修改

只要不希望更改指向的对象,就可以使用它:

例如,

def use_global_variable():
    return global_variable + '!!!'

现在我们可以使用全局变量:

>>> use_global_variable()
'Foo!!!'

从函数内部修改全局变量

要将全局变量指向另一个对象,需要再次使用 global 关键字:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

请注意,编写此函数后,实际上对其进行更改的代码仍未运行:

>>> use_global_variable()
'Foo!!!'

因此,在调用函数之后:

>>> change_global_variable()

我们可以看到全局变量已更改。现在, global_variable名称指向'Bar'

>>> use_global_variable()
'Bar!!!'

请注意,Python 中的 “全局” 不是真正的全局 - 只是模块级别的全局。因此,它仅适用于在全局模块中编写的函数。函数会记住编写它们的模块,因此当将它们导出到其他模块时,它们仍然会在创建它们的模块中查找全局变量。

具有相同名称的局部变量

如果创建具有相同名称的局部变量,它将覆盖全局变量:

def use_local_with_same_name_as_global():
    # bad name for a local variable, though.
    global_variable = 'Baz' 
    return global_variable + '!!!'

>>> use_local_with_same_name_as_global()
'Baz!!!'

但是使用名称错误的局部变量不会更改全局变量:

>>> use_global_variable()
'Bar!!!'

请注意,除非您确切知道自己在做什么并且有充分的理由这样做,否则应避免使用与全局变量同名的局部变量。我还没有遇到这样的原因。

使用并行执行,如果您不了解发生了什么,全局变量可能会导致意外结果。这是在多处理中使用全局变量的示例。我们可以清楚地看到,每个进程都使用其自己的变量副本:

import multiprocessing
import os
import random
import sys
import time

def worker(new_value):
    old_value = get_value()
    set_value(random.randint(1, 99))
    print('pid=[{pid}] '
          'old_value=[{old_value:2}] '
          'new_value=[{new_value:2}] '
          'get_value=[{get_value:2}]'.format(
          pid=str(os.getpid()),
          old_value=old_value,
          new_value=new_value,
          get_value=get_value()))

def get_value():
    global global_variable
    return global_variable

def set_value(new_value):
    global global_variable
    global_variable = new_value

global_variable = -1

print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after  set_value(), get_value() = [%s]' % get_value())

processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))

输出:

before set_value(), get_value() = [-1]
after  set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]

事实证明,答案总是很简单。

这是一个小样本模块,具有在main定义中显示它的简单方法:

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation

def isTheNumber():
    return helper

这是在main定义中显示它的方法:

import TestPy

def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())

if __name__ == '__main__':
    main()

这个简单的代码就是这样,它将执行。希望对您有所帮助。

您所说的是使用这样的方法:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

但是更好的方法是像这样使用全局变量:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

两者给出相同的输出。