为什么不需要“global”关键字来访问全局变量?
- 2024-11-21 08:33:00
- admin 原创
- 8
问题描述:
据我所知,Python 有一个用于函数的单独命名空间,所以如果我想在函数中使用全局变量,我应该使用global
。
但是,即使没有,我也可以访问全局变量global
:
>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
... return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'
为什么这会起作用?
另请参阅第一次使用后重新分配局部变量时出现的 UnboundLocalError,以了解在未指定的情况下尝试分配全局变量时发生的错误global
。有关如何使用全局变量的一般问题,请参阅在函数中使用全局变量。
解决方案 1:
该关键字global
仅在局部上下文中更改或创建全局变量时有用,尽管创建全局变量很少被认为是一个好的解决方案。
def bob():
me = "locally defined" # Defined only in local context
print(me)
bob()
print(me) # Asking for a global variable
以上内容将为您提供:
locally defined
Traceback (most recent call last):
File "file.py", line 9, in <module>
print(me)
NameError: name 'me' is not defined
而如果使用该global
语句,变量将在函数范围“之外”可用,从而有效地成为全局变量。
def bob():
global me
me = "locally defined" # Defined locally but declared as global
print(me)
bob()
print(me) # Asking for a global variable
因此上面的代码将给你:
locally defined
locally defined
此外,由于 Python 的特性,您还可以使用global
它在本地上下文中声明函数、类或其他对象。但我不建议这样做,因为如果出现问题或需要调试,它会带来噩梦。
解决方案 2:
虽然无需使用关键字即可访问全局变量global
,但如果您想修改它们,则必须使用global
关键字。例如:
foo = 1
def test():
foo = 2 # new local foo
def blub():
global foo
foo = 3 # changes the value of the global foo
就您而言,您只是访问列表sub
。
解决方案 3:
这是访问名称和在范围内绑定名称之间的区别。
如果您只是查找变量来读取其值,那么您可以访问全局和本地范围。
但是,如果您分配给一个变量的名称不在本地范围内,那么您就是将该名称绑定到此范围(并且如果该名称也作为全局名称存在,那么您将隐藏它)。
如果您希望能够分配给全局名称,则需要告诉解析器使用全局名称而不是绑定新的本地名称 - 这就是“global”关键字的作用。
在块中的任何位置进行绑定都会导致该块中所有位置的名称都被绑定,这可能会导致一些相当奇怪的后果(例如,UnboundLocalError 突然出现在以前正常工作的代码中)。
>>> a = 1
>>> def p():
print(a) # accessing global scope, no binding going on
>>> def q():
a = 3 # binding a name in local scope - hiding global
print(a)
>>> def r():
print(a) # fail - a is bound to local scope, but not assigned yet
a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
r()
File "<pyshell#32>", line 2, in r
print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>>
解决方案 4:
其他答案回答了你的问题。关于 Python 中的名称,另一个需要了解的重要事项是,它们根据作用域的不同,要么是本地的,要么是全局的。
例如:
value = 42
def doit():
print value
value = 0
doit()
print value
您可能猜到该value = 0
语句将分配给局部变量,而不会影响函数外部声明的相同变量的值doit()
。您可能会更惊讶地发现上面的代码无法运行。print value
函数内的语句会产生一个UnboundLocalError.
原因是 Python 注意到,在函数的其他地方,你分配了名称value
,并且也value
没有在任何地方声明global
。这使它成为一个局部变量。但是当你尝试打印它时,本地名称尚未定义。在这种情况下,Python不会像其他一些语言那样回退到将名称作为全局变量进行查找。本质上,如果你在函数的任何地方定义了同名的局部变量,你就无法访问全局变量。
解决方案 5:
访问名称和分配名称是不同的。 在您的例子中,您只是访问名称。
如果在函数内赋值给变量,除非声明为全局变量,否则该变量将被视为局部变量。如果没有声明全局变量,则将被视为全局变量。
>>> x = 1 # global
>>> def foo():
print x # accessing it, it is global
>>> foo()
1
>>> def foo():
x = 2 # local x
print x
>>> x # global x
1
>>> foo() # prints local x
2
解决方案 6:
无需关键字即可访问全局关键字
global
为了能够修改它们,您需要明确声明该关键字是全局的。否则,该关键字将在本地范围内声明。
例子:
words = [...]
def contains (word):
global words # <- not really needed
return (word in words)
def add (word):
global words # must specify that we're working with a global keyword
if word not in words:
words += [word]
解决方案 7:
Python FAQ 中对此进行了很好的解释
Python 中局部变量和全局变量的规则是什么?
在 Python 中,仅在函数内部引用的变量隐式为全局变量。如果在函数主体的任何地方为变量赋值,则除非明确声明为全局变量,否则该变量将被视为局部变量。
虽然一开始有点令人惊讶,但稍加考虑就能解释这一点。一方面,要求
global
分配变量可以防止意外的副作用。另一方面,如果global
要求所有全局引用都是这样,那么您将global
一直使用。您必须将对global
内置函数或导入模块组件的每个引用声明为。这种混乱会破坏声明global
在识别副作用方面的实用性。
解决方案 8:
global
使变量对模块(即模块范围)中的所有内容都可见,就像您在模块本身的顶层定义了它一样。它在模块外部不可见,并且只有在设置后才能从模块导入,所以不要担心,这不是它的用途。
何时global
解决实际问题?(注意:仅在 Python 3 上检查。)
# Attempt #1, will fail
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to
# do it automatically when importing this module
top_level_something_or_other = None
def foo1():
import catbus
# Now ``catbus`` is visible for anything else defined inside ``foo()``
# at *compile time*
bar() # But ``bar()`` is a call, not a definition. ``catbus``
# is invisible to it.
def bar():
# `bar()` sees what is defined in the module
# This works:
print(top_level_something_or_other)
# This doesn't work, we get an exception: NameError: name 'catbus' is not defined
catbus.run()
可以通过以下方法修复global
:
# Attempt #2, will work
# We still cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to
# do it automatically when importing this module
top_level_something_or_other = None
def foo2():
import catbus
global catbus # Now catbus is also visible to anything defined
# in the top-level module *at runtime*
bar()
def bar():
# `bar` sees what is defined in the module and when run what is available at run time
# This still works:
print(top_level_something_or_other)
# This also works now:
catbus.run()
如果像这样bar()
在内部定义,那么这就没有必要了:foo
# Attempt 3, will work
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to
# do it automatically when importing this module
top_level_something_or_other = None
def foo3():
def bar():
# ``bar()`` sees what is defined in the module *and* what is defined in ``foo()``
print(top_level_something_or_other)
catbus.run()
import catbus
# Now catbus is visible for anything else defined inside foo() at *compile time*
bar() # Which now includes bar(), so this works
通过定义bar()
外部foo()
,bar()
可以将其导入到可以直接导入的东西中catbus
,或者模拟它,就像在单元测试中一样。
global
是一种代码异味,但有时你需要的正是像这样的肮脏黑客global
。无论如何,“全局”对它来说是一个坏名字,因为在 python 中没有全局范围这样的东西,它一直都是模块。
解决方案 9:
任何在函数外部声明的变量都被视为全局变量,只有在函数内部(构造函数除外)声明它们时才必须指定该变量是全局的。
解决方案 10:
这意味着您不应该执行以下操作:
x = 1
def myfunc():
global x
# formal parameter
def localfunction(x):
return x+1
# import statement
import os.path as x
# for loop control target
for x in range(10):
print x
# class definition
class x(object):
def __init__(self):
pass
#function definition
def x():
print "I'm bad"
解决方案 11:
Global 使变量“全局”
def out():
global x
x = 1
print(x)
return
out()
print (x)
这使得“x”在函数外充当普通变量。如果你将全局变量取出,那么它会出错,因为它无法打印函数内的变量。
def out():
# Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
x = 1
print(x)
return
out()
print (x)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件