[Tutor] "farkadoodle" or: unique global names, was Re: Data persistence problem

Steven D'Aprano steve at pearwood.info
Sun Jun 23 04:24:38 CEST 2013


On 23/06/13 05:59, Albert-Jan Roskam wrote:

> I was playing around with this a bit and arrived at the following surprising (for me at least) result. I thought the global/local/nonlocal keywords could be used to get values from another scope. Though this could also happen implicitly, e.g. if only x = "I am global" is defined and x is used (and not redefined) inside a function, then python still knows this variable inside that function.


No, Python does not work that way, unlike (say) Lua where you can write code that fetches a global variable x and assigns it to a local variable x.

In Python, the presence of keywords nonlocal and global affect the entire function body, not just lines following them. They're also only needed when you assign to a variable. Looking up the variable's name does not require a declaration.

The rule Python follows goes something like this:


* If you assign to a name (e.g. "spam = 42") anywhere inside the body of a function, then that name is treated as a local variable, which is a fast lookup.

* Otherwise, it is treated as unknown scope, and Python will search nesting functions (if any), globals, and finally builtins for the name.


An example:

py> import builtins
py> builtins.a = "builtins"  # Kids, don't do this at home!
py> b = c = d = "global"
py> def f():
...     c = d = "nonlocal"
...     def g():
...             d = "local"
...             print(a, b, c, d)
...     g()
...
py> f()
builtins global nonlocal local



* If you wish to assign to a variable in another scope, you must declare it. You can only declare global and nonlocal. You cannot declare a variable is builtin (you're not supposed to write to the builtin scope), and there is no way to declare *which* nonlocal function scope you write to.

Other than that, you can write to the builtin scope directly, if you import it first, or the global scope by using globals(). But if you're doing either of these things, you probably shouldn't be.

Writing to the *local* scope via locals() is not guaranteed to work! It is a lot of fun (for some definition of fun) trying to determine under what circumstances it may or may not work, depending on the version and implementation of Python and even which scope you are in when you call locals().


-- 
Steven


More information about the Tutor mailing list