据我了解,Python 有一个单独的函数命名空间,所以如果我想在函数中使用全局变量,我可能应该使用 global
。
但是,即使没有 global
,我也能够访问全局变量:
>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
... return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'
我错过了什么吗?此外,以下来自 Python 文档:
全局语句中列出的名称不得定义为形式参数或 for 循环控制目标、类定义、函数定义或导入语句。
虽然形式参数和类定义对我来说很有意义,但我无法理解 for 循环控制目标和函数定义的限制。
def foo(): ...
和 foo = ...
)。它确实为每个函数调用创建了一个新范围。 (但这与世界上所有其他远程高级语言有何不同?)
关键字 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
在本地上下文中声明函数、类或其他对象。尽管我建议不要这样做,因为如果出现问题或需要调试,它会导致噩梦。
虽然您可以在没有 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
。
foo = 3
没有全局工作,但 foo 在 blub
函数范围和本地再次定义不修改原始 foo 变量。这让我很困惑。
blub()
时,函数外部的 foo
确实按预期绑定到 3。
blub()
按预期工作。没有的是 test()
:创建了新的本地 foo
,而全局 foo
保留了价值。
这是在范围内访问名称和 binding 它之间的区别。
如果您只是查找一个变量来读取它的值,那么您可以访问全局范围和局部范围。
但是,如果您分配给名称不在本地范围内的变量,则将该名称绑定到此范围内(如果该名称也作为全局名称存在,则将其隐藏)。
如果您希望能够分配给全局名称,则需要告诉解析器使用全局名称而不是绑定新的本地名称 - 这就是“全局”关键字的作用。
绑定块中的任何位置会导致该块中任何位置的名称都被绑定,这可能会导致一些看起来很奇怪的后果(例如 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
>>>
其他答案回答你的问题。关于 Python 中的名称要了解的另一件重要事情是,它们在每个范围内都是本地的或全局的。
考虑一下,例如:
value = 42
def doit():
print value
value = 0
doit()
print value
您可能会猜到 value = 0
语句将分配给一个局部变量,并且不会影响在 doit()
函数之外声明的同一变量的值。您可能会更惊讶地发现上面的代码不会运行。函数内的语句 print value
产生一个 UnboundLocalError.
原因是 Python 已经注意到,在函数的其他地方,您指定了名称 value
,而且 value
也没有声明为 global
。这使它成为一个局部变量。但是当您尝试打印它时,尚未定义本地名称。在这种情况下,Python 不会像其他一些语言那样将名称作为全局变量来查找。本质上,如果您在函数中定义了同名的局部变量anywhere,则无法访问全局变量。
global
(或 Python 3.x 中的 nonlocal
)会覆盖此行为并允许您重新分配外部名称。
let
声明的变量是not 提升的。
global
声明的全局变量是否更快,或者没关系?
访问名称和分配名称是不同的。在您的情况下,您只是在访问一个名称。
如果您在函数中分配给变量,则该变量被假定为局部变量,除非您将其声明为全局变量。如果没有,则假定它是全局的。
>>> 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
您可以在没有关键字 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]
这在 Python FAQ 中有很好的解释
Python中局部变量和全局变量的规则是什么?在 Python 中,仅在函数内部引用的变量是隐式全局的。如果一个变量在函数体内的任何地方都被赋值,除非明确声明为全局变量,否则它被假定为局部变量。虽然起初有点令人惊讶,但片刻的考虑解释了这一点。一方面,对已分配的变量要求全局性提供了防止意外副作用的障碍。另一方面,如果所有全局引用都需要全局,那么您将一直使用全局。您必须将对内置函数或导入模块组件的每个引用声明为全局。这种混乱会破坏全局声明识别副作用的有用性。
任何在函数外部声明的变量都被假定为全局变量,只有在从函数内部(构造函数除外)声明它们时,您必须指定该变量是全局变量。
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
通过在 foo()
之外定义 bar()
,可以将 bar()
导入到可以直接导入 catbus
的内容中,或者模拟它,例如在单元测试中。
global
是一种代码味道,但有时您需要的正是像 global
这样的肮脏 hack。无论如何,“全局”对它来说是个坏名字,因为在 python 中没有全局范围之类的东西,它一直是模块。
这意味着您不应执行以下操作:
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"
全局使变量“全局”
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)
不定期副业成功案例分享
globals
之类的东西(谢天谢地)。正如您正确指出的那样,全局绑定到模块内的命名空间,但是它可以作为from module import variable
或import module.variable
导入另一个模块。在第一种情况下,导入将使变量可以作为variable
访问,而不需要作为module.
引用。如果它在模块范围内被认为是全局的,则取决于它的导入位置。另请参阅nonlocal
作为 python 3 中与范围相关的新关键字。global
基本上只对在本地范围内定义或启动全局变量有用?