ChatGPT解决这个技术问题 Extra ChatGPT

Use of "global" keyword in Python

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 global variable even without global:

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Am I missing anything? Also, following is from Python documentation:

Names listed in a global statement must not be defined as formal parameters or in a for loop control target, class definition, function definition, or import statement.

While formal parameters and class definition make sense to me, I'm not able to understand the restriction on for loop control target and function definition.

I think you are confused with php which requires the use of the global keyword - the python docs confirm this - basicly if it isn't defined in the local context it is treated as global
Be careful with your wording: Python does not have a seperate namespace for functions (that would mean you could have def foo(): ... and foo = ... at the same time). It does create a new scope for every function call. (But how is this different from about every other remotely high-level language in the world?)

p
phoenix

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.


"global" in this context appears to be different from other languages consider "global". In Python a "global" reference is still in the confines of the module and would need to be referenced from outside that module as "module.global_var" rather than simply "global_var" as one might expect.
@juice - In Python there is no such thing as absolute globals automatically defined across all namespaces (thankfully). As you correctly pointed out, a global is bound to a namespace within a module, however it can be imported into another module as from module import variable or import module.variable. In the first case, the import would make the variable accessible as variable without requiring reference as module.. If it's considered a global in the scope of the module will depend on where it's imported. See also nonlocal as a new scope related keyword in python 3.
Could you explain why global variables are not a good solution? I often hear this, but in my current project they seem to do just what I need them to do. Is there something more sinister I haven't thought of?
@RobinNewhouse There's a few questions on SO already covering that topic and other non SO articles.
@phoenix sooo global is basically only useful for defining or initiating global variables from within a local scope?
S
SherylHohman

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.


With one caveat: foo = 3 without global works, but foo is defined again locally in blub function scope & does not modify original foo variable. This was quite confusing to me.
@chhantyal if by works you mean that it doesn't throw an error, you are correct, but in Ivo Wetzel's context it would not be functioning as intended. There are uses for such behavior, but it is often not what the programmer wants.
Can somebody explain the comment by @chhantyal or @democidist? When I try this code (with Python 3) and call blub(), the foo outside the function does get bound to 3, as intended.
@LarryEngholm, blub() works as intended. It's test() that doesn't: there is new, local foo created and global foo retains value.
keep in mind that dict values, or index list values, DO change even without the global keyword. stackoverflow.com/questions/14323817/…
p
pycruft

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

very counterintuitive, hard to believe that this is valid python code
k
kindall

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.


Thanks for pointing this out. So, as long as your local scope doesn't assign to a name that exists outside of it, then references in the local scope will use the outside name. However, if anywhere in your function you do assign to that name, references in that local scope, even before the local assignment, do not look outside.
Exactly, you've got it. global (or nonlocal in Python 3.x) overrides this behavior and allows you to re-assign the external name.
In other languages, this seems to be referred to as "hoisting", like this for example: github.com/shichuan/javascript-patterns/blob/master/…
To add insult to injury, variables declared with the the newer JavaScript keyword let are not hoisted.
Is it faster to access a global variable declared with global or it doesn't matter?
u
user225312

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

m
martynas

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]

C
Community

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, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python


J
Jesus Ramos

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.


k
kaleissin

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.


i
ikostia

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"

ikostia is enumerating all the things you can't use 'x' for having used global - docs.python.org/reference/…
@Unode: I'm just demonstating all the cases that NikhilRathod gave in his quote.
M
Michael

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)