53

If a function needs to modify a variable declared in global scope, it need to use the global declaration. However, if the function just needs to read a global variable it can do so without using a global declaration:

X = 10
def foo():
    global X
    X = 20 # Needs global declaration
def bar():
    print( X ) # Does not need global

My question is about the design of Python: why is Python designed to allow the read of global variables without using the global declaration? That is, why only force assignment to have global, why not force global upon reads too? (That would make it even and elegant.)

Note: I can see that there is no ambiguity while reading, but while assigning it is not clear if one intends to create a new local variable or assign to the global one. But, I am hoping there is a better reason or intention to this uneven design choice by the BDFL.

Ashwin Nanjappa
  • 76,204
  • 83
  • 211
  • 292

4 Answers4

35

With nested scopes, the variable lookups are easy. They occur in a chain starting with locals, through enclosing defs, to module globals, and then builtins. The rule is the first match found wins. Accordingly, you don't need a "global" declaration for lookups.

In contrast, with writes you need to specify which scope to write to. There is otherwise no way to determine whether "x = 10" in function would mean "write to a local namespace" or "write to a global namespace."

Executive summary, with write you have a choice of namespace, but with lookups the first-found rule suffices. Hope this helps :-)

Edit: Yes, it is this way "because the BDFL said so", but it isn't unusual in other languages without type declarations to have a first-found rule for lookups and to only require a modifier for nonlocal writes. When you think about it, those two rules lead to very clean code since the scope modifiers are only needed in the least common case (nonlocal writes).

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
24

Look at this code:

from module import function

def foo(x):
    return function(x)

The name function here is a global. It would get awfully tedious if I had to say global function to get this code to work.

Before you say that your X and my function are different (because one is a variable and the other is an imported function), remember that all names in Python are treated the same: when used, their value is looked up in the scope hierarchy. If you needed global X then you'd need global function. Ick.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 7
    That doesn't really answer the question though. You could extend this argument to modifying globals too. Why the explicit global for modifying globals? – jterrace Apr 28 '12 at 03:19
  • 5
    Because if you don't include `global X` the statement `X = 10` would create a local `X` bound to `10` rather than rebinding the global `X` to `10`. – Dan D. Apr 28 '12 at 03:20
  • 5
    @jterrace: the question was "Why is global needed *only* on assignment?," not, "why is global needed on assignment." – Ned Batchelder Apr 28 '12 at 03:26
  • 7
    Actually, that's the question title. The real question is: _why is Python designed to allow the read of global variables without using the global declaration, but not modify?_ – Pedro Werneck Apr 28 '12 at 03:53
  • 1
    Predro: Ned is answering my actual question. I am sorry if I confused readers with my English. I have corrected the question text too now. – Ashwin Nanjappa Apr 28 '12 at 05:29
24

Because explicit is better than implicit.

There's no ambiguity when you read a variable. You always get the first one found when searching scopes up from local until global.

When you assign, there's only two scopes the interpreter may unequivocally assume you are assigning to: local and global. Since assigning to local is the most common case and assigning to global is actually discouraged, it's the default. To assign to global you have to do it explicitly, telling the interpreter that wherever you use that variable in this scope, it should go straight to global scope and you know what you're doing. On Python 3 you can also assign to the nearest enclosing scope with 'nonlocal'.

Remember that when you assign to a name in Python, this new assignment has nothing to do with that name previously existing assigned to something else. Imagine if there was no default to local and Python searched up all scopes trying to find a variable with that name and assigning to it as it does when reading. Your functions' behavior could change based not only on your parameters, but on the enclosing scope. Life would be miserable.

Pedro Werneck
  • 40,902
  • 7
  • 64
  • 85
  • 8
    As a side note which doesn't particularly fit the answer, I've been programming in Python professionally for 8 years and I **never** used global for anything. – Pedro Werneck Apr 28 '12 at 03:45
  • 1
    Pedro: If you are writing a simple script whose function needs to modify global state, what do you do? What if classes are too heavy for the simple script? – Ashwin Nanjappa Apr 28 '12 at 05:33
7

You say it yourself that with reads there is no ambiguity and with writes there is. Therefore you need some mechanism for resolving the ambiguity with writes.

One option (possibly actually used by much older versions of Python, IIRC) is to just say writes always go to the local scope. Then there's no need for a global keyword, and no ambiguity. But then you can't write to global variables at all (without using things like globals() to get at them in a round-about way), so that wouldn't be great.

Another option, used by languages that statically declare variables, is to communicate to the language implementation up-front for every scope which names are local (the ones you declare in that scope) and which names are global (names declared at the module scope). But Python doesn't have declared variables, so this solution doesn't work.

Another option would be to have x = 3 assign to a local variable only if there isn't already a name in some outer scope with name x. Seems like it would intuitively do the right thing? It would lead to some seriously nasty corner cases though. Currently, where x = 3 will write to is statically determined by the parser; either there's no global x in the same scope and it's a local write, or there is a global x and it's a global write. But if what it will do depends on the global module scope, you have to wait until runtime to determine where the write goes which means it can change between invocations of a function. Think about that. Every time you create a global in a module, you would alter the behaviour of all functions in the module that happened to be using that name as a local variable name. Do some module scope computation that uses tmp as a temporary variable and say goodbye to using tmp in all functions in the module. And I shudder to think of the obscure bugs involving assigning an attribute on a module you've imported and then calling a function from that module. Yuck.

And another option is to communicate to the language implementation on each assignment whether it should be local or global. This is what Python has gone with. Given that there's a sensible default that covers almost all cases (write to a local variable), we have local assignment as the default and explicitly mark out global assignments with global.


There is an ambiguity with assignments that needs some mechanism to resolve it. global is one such mechanism. It's not the only possible one, but in the context of Python, it seems that all the alternative mechanisms are horrible. I don't know what sort of "better reason" you're looking for.

Ben
  • 68,572
  • 20
  • 126
  • 174
  • Ben: Python newbie here. Is it possible to "inject" a new global variable at runtime apart from the ones already listed in the source code at global scope? Your answers seems to indicate this, I would like to know how this is possible. – Ashwin Nanjappa Apr 28 '12 at 05:37
  • 1
    @Ashwin The global scope isn't any different than any other scope. There is no single static declaration of what it contains; Python simply executes the code in a module, as a result of which names are assigned in the global scope. This is exactly the same way that names are defined in local scope. On top of that, any other code with a reference to the module (after importing it) can assign attribtues on it, and module attributes are just the global variables within that module. Plus functions in the module could use `global`. Is that the sort of thing you're referring to? – Ben Apr 28 '12 at 06:10