在函数中使用全局变量

问:

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

如何使用在其他函数中的一个函数中定义的全局变量?

答1:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

您可以在其他函数中使用全局变量,方法是在为其分配值的每个函数中将其声明为 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

由于不清楚 globvar = 1 是创建局部变量还是更改全局变量,Python 默认创建局部变量,并让您使用 global 关键字显式选择其他行为。

如果您想跨模块共享全局变量,请参阅其他答案。

将全局变量称为“如此危险”是极端夸张的。 Globals 在每一种曾经存在和将要存在的语言中都非常好。他们有他们的位置。您应该说的是,如果您不知道如何编程,它们可能会导致问题。

我认为它们相当危险。然而在 python 中,“全局”变量实际上是模块级的,它解决了很多问题。

答2:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

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

假设你有一个这样的模块:

# sample.py
_my_global = 5

def func1():
    _my_global = 42

def func2():
    print _my_global

func1()
func2()

您可能希望这会打印 42,但实际上它会打印 5。如前所述,如果您将“global”声明添加到 func1(),那么 func2() 将打印 42。

def func1():
    global _my_global 
    _my_global = 42

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

因此,当您将 42 分配给名称 _my_global 时,Python 会创建一个隐藏同名全局变量的局部变量。当 func1() 返回时,该本地超出范围并为 garbage-collected;同时,func2() 除了(未修改的)全局名称外,什么都看不到。请注意,这个命名空间决定发生在编译时,而不是运行时——如果您在分配给它之前读取 func1() 内的 _my_global 的值,您会得到一个 UnboundLocalError,因为 Python 已经决定它必须是一个局部变量,但它还没有任何与之关联的值。但是通过使用“global”语句,您告诉 Python 它应该在别处寻找名称,而不是在本地分配给它。

(我相信这种行为主要源于对本地命名空间的优化——如果没有这种行为,Python 的 VM 将需要在每次将新名称分配给函数内部时执行至少三个名称查找(以确保名称没有t 已经存在于模块/内置级别),这将显着减慢非常常见的操作。)

您提到命名空间决定发生在编译时,我认为这不是真的。从我学到的python的编译only checks for syntax error, not name error试试这个例子def A(): x+=1,如果你不运行它会不会给出UnboundLocalError,拜托验证谢谢

对于像 MyGlobal = 5 这样的全局变量,通常使用大写字母

@watashiSHUN:命名空间决定确实发生在编译时。确定 x 是本地的不同于在运行时检查本地名称是否在第一次使用之前绑定到某个值。

@Vassilis:大写 all 字母很常见:MY_GLOBAL = 5。请参阅 Style Guide for Python Code。

答3:

huntsbot.com – 高效赚钱,自由工作

您可能想探索 namespaces 的概念。在 Python 中,module 是 global 数据的自然位置:

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

此处描述了 global-in-a-module 的特定用法 - How do I share global variables across modules?,为了完整起见,此处共享内容:

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

文件:config.py

x = 0 # ‘x’ 配置设置的默认值

文件:mod.py

import config
config.x = 1

文件:main.py

import config
import mod
print config.x

由于我不喜欢 config.x 的原因,我可以摆脱它吗?我带来了 x = lambda: config.x,然后我在 x() 中获得了 new 值。出于某种原因,拥有 a = config.x 并不能解决我的问题。

@vladosaurus from config import x 解决了这个问题吗?

答4:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

启发式查找绑定操作。赋值是一种这样的操作,导入另一种。但是 for 循环的目标以及 with 和 except 语句中 as 之后的名称也被绑定到。

@MartijnPieters 对于 except 子句中 as 之后的名称,这对我来说并不明显。但它会自动删除以节省内存。

@Robert:不是为了节省内存,而是为了避免创建循环引用,这可能导致内存泄漏。这是因为异常引用了回溯,而回溯引用了整个调用堆栈中的每个本地和全局命名空间,包括异常处理程序中的 as ... 目标。

答5:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

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

但是,如果您分配给未在函数中声明为全局的新变量,它会被隐式声明为局部,并且它可以覆盖任何现有的同名全局变量。

此外,全局变量很有用,这与一些 OOP 狂热者声称的相反——尤其是对于较小的脚本,因为 OOP 是多余的。

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

绝对重新。狂热者。大多数 Python 用户使用它来编写脚本并创建小函数来分离出少量代码。

答6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

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

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

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

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

我们在类中得到相同的行为

后续评论询问:

如果我想在一个类的函数内创建一个全局变量,并想在另一个类的另一个函数内使用该变量,该怎么办?

在这里,我演示了我们在方法中获得与在常规函数中相同的行为:

class Foo:
    def foo(self):
        global global_variable
        global_variable = 'Foo'

class Bar:
    def bar(self):
        return global_variable + '!!!'

Foo().foo()

现在:

>>> Bar().bar()
'Foo!!!'

但我建议不要使用全局变量,而是使用类属性,以避免混淆模块命名空间。另请注意,我们在这里不使用 self 参数 - 这些可能是类方法(如果从通常的 cls 参数中改变类属性,则很方便)或静态方法(没有 self 或 cls)。

很酷,但是如果我想在一个类的函数内创建一个全局变量并想在另一个类的另一个函数内使用该变量怎么办?有点卡在这里

@anonmanx我不知道你为什么卡住,它在方法中的行为与在常规函数中的行为相同。但是我会用你的评论和一些演示代码来更新我的答案,好吗?

好,知道了。因此,我将不得不显式调用该函数以使用该全局变量。

答7:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

除了已经存在的答案并使这更加混乱:

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

来源:What are the rules for local and global variables in Python?。

答8:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

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]

答9:

huntsbot.com – 高效赚钱,自由工作

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

下面是一个小示例模块,它以一种简单的方式在 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()

这个简单的代码就是这样工作的,它会执行。我希望它有所帮助。

谢谢,我是python新手,但对java有点了解。你说的对我有用。并在类中编写 global a 对我来说似乎比在编写“global a”的函数中更有意义。我注意到你不能说 global a=4

这对我来说可能是最简单但非常有用的 Python 技巧。我将此模块命名为 global_vars,并初始化在启动脚本中调用的 init_global_vars 中的数据。然后,我只需为每个定义的全局变量创建访问器方法。我希望我可以多次投票!谢谢彼得!

如果有很多全局变量并且我不想在全局语句之后一个一个地列出它们怎么办?

答10:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

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

globvar = 5

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

f()  # Prints 5

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

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

两者都给出相同的输出。

答11:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

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

如下:

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]
"""

“在您要使用的每个功能中”有点不正确,应该更接近:“在您要更新的每个功能中”

原文链接:https://www.huntsbot.com/qa/QQDg/using-global-variables-in-a-function?lang=zh_CN&from=csdn

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值