Why isn't the 'global' keyword needed to access a global variable?
From my understanding, Python has a separate namespace for functions, so if I want to use a global variable in a function, I should probably use global
.
However, I was able to access a glo开发者_运维问答bal variable even without global
:
>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
... return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'
Why does this work?
See also UnboundLocalError on local variable when reassigned after first use for the error that occurs when attempting to assign to the global variable without global
. See Using global variables in a function for the general question of how to use globals.
The keyword global
is only useful to change or create global variables in a local context, although creating global variables is seldom considered a good solution.
def bob():
me = "locally defined" # Defined only in local context
print(me)
bob()
print(me) # Asking for a global variable
The above will give you:
locally defined
Traceback (most recent call last):
File "file.py", line 9, in <module>
print(me)
NameError: name 'me' is not defined
While if you use the global
statement, the variable will become available "outside" the scope of the function, effectively becoming a global variable.
def bob():
global me
me = "locally defined" # Defined locally but declared as global
print(me)
bob()
print(me) # Asking for a global variable
So the above code will give you:
locally defined
locally defined
In addition, due to the nature of python, you could also use global
to declare functions, classes or other objects in a local context. Although I would advise against it since it causes nightmares if something goes wrong or needs debugging.
While you can access global variables without the global
keyword, if you want to modify them you have to use the global
keyword. For example:
foo = 1
def test():
foo = 2 # new local foo
def blub():
global foo
foo = 3 # changes the value of the global foo
In your case, you're just accessing the list sub
.
This is the difference between accessing the name and binding it within a scope.
If you're just looking up a variable to read its value, you've got access to global as well as local scope.
However if you assign to a variable who's name isn't in local scope, you are binding that name into this scope (and if that name also exists as a global, you'll hide that).
If you want to be able to assign to the global name, you need to tell the parser to use the global name rather than bind a new local name - which is what the 'global' keyword does.
Binding anywhere within a block causes the name everywhere in that block to become bound, which can cause some rather odd looking consequences (e.g. UnboundLocalError suddenly appearing in previously working code).
>>> 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
>>>
The other answers answer your question. Another important thing to know about names in Python is that they are either local or global on a per-scope basis.
Consider this, for example:
value = 42
def doit():
print value
value = 0
doit()
print value
You can probably guess that the value = 0
statement will be assigning to a local variable and not affect the value of the same variable declared outside the doit()
function. You may be more surprised to discover that the code above won't run. The statement print value
inside the function produces an UnboundLocalError.
The reason is that Python has noticed that, elsewhere in the function, you assign the name value
, and also value
is nowhere declared global
. That makes it a local variable. But when you try to print it, the local name hasn't been defined yet. Python in this case does not fall back to looking for the name as a global variable, as some other languages do. Essentially, you cannot access a global variable if you have defined a local variable of the same name anywhere in the function.
Accessing a name and assigning a name are different. In your case, you are just accessing a name.
If you assign to a variable within a function, that variable is assumed to be local unless you declare it global. In the absence of that, it is assumed to be 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
- You can access global keywords without keyword
global
- To be able to modify them you need to explicitly state that the keyword is global. Otherwise, the keyword will be declared in local scope.
Example:
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]
This is explained well in the Python FAQ
What are the rules for local and global variables in Python?
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.
Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring
global
for assigned variables provides a bar against unintended side-effects. On the other hand, ifglobal
was required for all global references, you’d be usingglobal
all the time. You’d have to declare asglobal
every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of theglobal
declaration for identifying side-effects.
https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
Any variable declared outside of a function is assumed to be global, it's only when declaring them from inside of functions (except constructors) that you must specify that the variable be global.
global
makes the variable visible to everything in the module, the modular scope, just as if you had defined it at top-level in the module itself. It's not visible outside the module, and it cannot be imported from the module until after it has been set, so don't bother, that's not what it is for.
When does global
solve real problems? (Note: Checked only on 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()
This can be fixed with 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()
This wouldn't be necessary if bar()
was defined inside foo
like so:
# 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
By defining bar()
outside of foo()
, bar()
can be imported into something that can import catbus
directly, or mock it, like in a unit test.
global
is a code smell, but sometimes what you need is exactly a dirty hack like global
. Anyway, "global" is a bad name for it as there is no such thing as global scope in python, it's modules all the way down.
It means that you should not do the following:
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"
Global makes the variable "Global"
def out():
global x
x = 1
print(x)
return
out()
print (x)
This makes 'x' act like a normal variable outside the function. If you took the global out then it would give an error since it cannot print a variable inside a function.
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)
精彩评论