首页 文章

在函数中使用全局变量

提问于
浏览
2619

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

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

18 回答

  • 5

    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 变量 .

  • 3666

    您需要在要使用的每个函数中引用全局变量 .

    如下:

    var = "test"
    
    def printGlobalText():
        global var #wWe are telling to explicitly use the global version
        var = "global from printGlobalText fun."
        print "var from printGlobalText: " + var
    
    def printLocalText():
        #We are NOT telling to explicitly use the global version, so we are creating a local variable
        var = "local version from printLocalText fun"
        print "var from printLocalText: " + var
    
    printGlobalText()
    printLocalText()
    """
    Output Result:
    var from printGlobalText: global from printGlobalText fun.
    var from printLocalText: local version from printLocalText
    [Finished in 0.1s]
    """
    
  • 689

    您可以在其他函数中使用全局变量,方法是在分配给它的每个函数中将其声明为 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 关键字来确保你真的知道's what you'正在玩 .

    如果要跨模块共享全局变量,请参阅其他答案 .

  • 21

    您可能想要探索namespaces的概念 . 在Python中,module是全局数据的自然位置:

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

    此处描述了global-in-a-module的特定用法 - how-do-i-share-global-variables-across-modules,为了完整性,内容在此处共享:

    在单个程序中跨模块共享信息的规范方法是创建一个特殊的配置模块(通常称为config或cfg) . 只需在应用程序的所有模块中导入配置模块;然后该模块可用作全局名称 . 因为每个模块只有一个实例,所以对模块对象所做的任何更改都会反映在任何地方 . 例如:File: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
    
  • 186

    接下来,作为一个补充,使用一个文件来包含所有在本地声明的全局变量,然后'import as':

    文件initval.py

    Stocksin = 300
    Prices = []
    

    文件getstocks.py

    import  initval as  iv
    
    Def   getmystocks (): 
         iv.Stocksin  = getstockcount ()
    
    
    Def getmycharts ():
        For ic in range (0,iv.Stocksin):
    

    .....

  • 11

    引用要在其中显示更改的类命名空间 .

    在此示例中,runner正在使用文件配置中的 max . 我希望我的测试在跑步者使用它时改变 max 的值 .

    main/config.py

    max = 15000
    

    main/runner.py

    from main import config
    def check_threads():
        return max < thread_count
    

    tests/runner_test.py

    from main import runner                # <----- 1. add file
    from main.runner import check_threads
    class RunnerTest(unittest):
       def test_threads(self):
           runner.max = 0                  # <----- 2. set global 
           check_threads()
    
  • 34

    如果您有一个具有相同名称的局部变量,您可能想要使用globals() function .

    globals()['your_global_var'] = 42
    
  • 11

    如果我正确理解您的情况,您所看到的是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假定在函数内的任何位置分配的任何名称都是该函数的本地名称,除非另有明确说明 . 如果只是从名称中读取,并且名称不是全局范围) .

    因此,当您为名称 myGlobal 分配42时,Python会创建一个局部变量,该变量将隐藏同名的全局变量 . 当本地超出范围时garbage-collected返回时为garbage-collected;同时, func2() 除了(未修改的)全局名称之外永远不会看到任何其他内容 . 请注意,此命名空间决策发生在编译时,而不是在运行时 - 如果您在分配给它之前在 func1() 内读取 myGlobal 的值,则会得到 UnboundLocalError ,因为Python已经确定它必须是本地的变量,但它还没有任何与之相关的值 . 但是通过使用' global '语句,您告诉Python它应该在其他地方查找名称而不是在本地分配它 .

    (我相信这种行为很大程度上是由于本地命名空间的优化 - 没有这种行为,每次在函数内部分配新名称时,Python的VM都需要执行至少三次名称查找(以确保名称没有' t已经存在于模块/内置级别),这将显着减慢非常常见的操作 . )

  • 5

    我添加了这个,因为我没有在任何其他答案中看到它,它可能对某些类似的东西挣扎有用 . globals()函数返回一个可变的全局符号字典,您可以“神奇地”为其余代码提供数据 . 例如:

    from pickle import load
    def loaditem(name):
        with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
            globals()[name] = load(openfile)
        return True
    

    from pickle import dump
    def dumpfile(name):
        with open(name+".dat", "wb") as outfile:
            dump(globals()[name], outfile)
        return True
    

    只允许您将变量转储/加载到全局命名空间中 . 超级方便,没有麻烦,没有大惊小怪 . 很确定它只是python 3 .

  • 53

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

    这是一个小样本模块,它以一种简单的方式在 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()
    

    这个简单的代码就像这样,它将执行 . 我希望它有所帮助 .

  • 39

    试试这个:

    def x1():
        global x
        x = 6
    
    def x2():
        global x
        x = x+1
        print x
    
    x = 5
    x1()
    x2()  # output --> 7
    
  • 20

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

    我们可以使用以下函数创建一个全局:

    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!!!'
    

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

  • 18

    你要说的是使用这样的方法:

    globvar = 5
    
    def f():
        var = globvar
        print(var)
    
    f()  # Prints 5
    

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

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

    两者都给出相同的输出 .

  • 12

    实际上,您并未将全局存储在局部变量中,只是创建对原始全局引用所引用的同一对象的本地引用 . 请记住,Python中的所有内容都是一个引用对象的名称,并且在通常的操作中不会复制任何内容 .

    如果您不必明确指定标识符何时引用预定义的全局,那么您可能必须明确指定标识符何时是新的局部变量(例如,使用类似'var'命令的内容在JavaScript中看到) . 由于局部变量在任何严重且非平凡的系统中比全局变量更常见,因此Python的系统在大多数情况下更有意义 .

    您可以使用一种尝试猜测的语言,使用全局变量(如果存在)或创建局部变量(如果不存在) . 但是,这将非常容易出错 . 例如,导入另一个模块可能会无意中引入该名称的全局变量,从而改变程序的行为 .

  • 77

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

    但是,如果分配给函数中未声明为全局的新变量,则它将隐式声明为local,并且它可以掩盖具有相同名称的任何现有全局变量 .

    此外,全局变量是有用的,与一些声称不同的OOP狂热者相反 - 特别是对于较小的脚本,其中OOP是过度的 .

  • 19

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

    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))
    

    Output:

    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]
    
  • 30

    除了已经存在的答案,并使这更令人困惑:

    在Python中,仅在函数内引用的变量是隐式全局变量 . 如果在函数体内的任何位置为变量分配了一个新值,则假定它是一个局部变量 . 如果在函数内部为变量赋予了新值,则该变量隐式为局部变量,您需要将其显式声明为“全局” . 虽然是起初有点令人惊讶,片刻的考虑解释了这一点 . 一方面,要求全局指定变量可以防止意外的副作用 . 另一方面,如果所有全局引用都需要全局,那么您将始终使用全局 . 您必须将对内置函数或导入模块的组件的每个引用声明为全局 . 这种混乱会破坏全球声明识别副作用的有用性 .

    资料来源:What are the rules for local and global variables in Python? .

  • 14

    写入全局数组的显式元素显然不需要全局声明,尽管写入“批发”确实有这样的要求:

    import numpy as np
    
    hostValue = 3.14159
    hostArray = np.array([2., 3.])
    hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
    
    def func1():
        global hostValue    # mandatory, else local.
        hostValue = 2.0
    
    def func2():
        global hostValue    # mandatory, else UnboundLocalError.
        hostValue += 1.0
    
    def func3():
        global hostArray    # mandatory, else local.
        hostArray = np.array([14., 15.])
    
    def func4():            # no need for globals
        hostArray[0] = 123.4
    
    def func5():            # no need for globals
        hostArray[1] += 1.0
    
    def func6():            # no need for globals
        hostMatrix[1][1] = 12.
    
    def func7():            # no need for globals
        hostMatrix[0][0] += 0.33
    
    func1()
    print "After func1(), hostValue = ", hostValue
    func2()
    print "After func2(), hostValue = ", hostValue
    func3()
    print "After func3(), hostArray = ", hostArray
    func4()
    print "After func4(), hostArray = ", hostArray
    func5()
    print "After func5(), hostArray = ", hostArray
    func6()
    print "After func6(), hostMatrix = \n", hostMatrix
    func7()
    print "After func7(), hostMatrix = \n", hostMatrix
    

相关问题