5 ms·
The "global" keyword in Python binds a name to the scope of the top level of the enclosing module. The "nonlocal" keyword is a Python 3.x feature which binds a
by picomancer 13y ago
The "global" keyword in Python binds a name to the scope of the top level of the enclosing module. The "nonlocal" keyword is a Python 3.x feature which binds a name to the next enclosing scope level.
So you would do:
a = 1
def contrived():
global a # I added this
a = 2
return a
contrived() # 2
a # 2
The "nonlocal" keyword would give the same result if the outer scope is the top level of the module. If the entire above code is itself enclosed in a function like so:
def enclose():
a = 1
def contrived():
nonlocal a
a = 2
return a
contrived() # 2
a # 2
You need "nonlocal" to refer to the "a" that's a local variable in enclose(). I.e. "global" gets you the top level, "nonlocal" gets you the next enclosing level.
The keyword is only necessary when you're assigning to an out-of-scope variable. If you remove the assignment statement "a = 2" from the function, the program will correctly read and return the value of a from the enclosing scope.
In other words, by default the set of names considered to be local variables in a function is the set of names that are the target of an assignment statement. Usually the default behavior is what you want, but if you wish to override it, use the "global" or "nonlocal" keyword.
From a design standpoint, I've learned over the years that global / nonlocal keywords are a "smell" that frequently indicates poor architecture, usually of the sort that the oft-cited "global variables are evil" doctrine is intended to protect against. Code that extensively uses these keywords should usually be refactored into a class, with the formerly global names instead being attributes (member variables).
- cursork 13y agoNot completely seriously.. This is why some of us prefer Perl ;) my $a = 1; my $contrived = sub { my $a = 2; # new lexical variable $a $a = 3; # if the my above wasn't there, outer $a would be 3 ... } say $a; # 1 Explicit declaration of the scope of a variable at initialisation is awesome. 'global' and 'nonlocal' feel weird/less consistent/like a workaround. People are used to creating variables 'on the fly' in Python / CoffeeScript - both break (for a certain value of 'break') certain assumptions in certain circumstances. I've never heard anyone ever complain about perl's lexical 'my'.. It even catches - with a warning - multiple my declarations that will clobber each other. You don't see that in other languages that often.
- picomancer 13y agoIf you've ever programmed in JavaScript -- and most people have, it's the language of the Web -- you will know that it is very easy to accidentally omit the "var" keyword and unintentionally pollute the global namespace. Such a bug likely will not manifest until someone else writes completely unrelated code that uses the same variable name by coincidence. Explicit declaration of the scope of a variable at initialization leads to unintended global namespace pollution when omitting the declaration is legal and causes the variable to be placed in the global scope, which can be difficult to diagnose because it is usually completely silent until unrelated code happens to interact by using the same name. From a language design standpoint, this means that you should either require a declaration which determines scope (C or Java), or have local be the default for variables whose scope is undeclared (Python). > I've never heard anyone ever complain about perl's lexical 'my' That's because programmers who care about good syntax in their languages don't use Perl.
- cursork 13y ago> Explicit declaration of the scope of a variable at initialization leads to unintended global namespace pollution when omitting the declaration is legal and causes the variable to be placed in the global scope Ah, but it's not legal with 'use strict;' (which everyone uses) > That's because programmers who care about good syntax in their languages don't use Perl. And Lisp has too many parentheses. I clearly just like my code to be illegible.
- emn13 13y agoYeah - back when coffeescript was new this was an argument, but with "use strict", the likelihood of accidental mis-assignments is actually considerably slower in javascript than in coffeescript. In javascript you'll get an error assigning to a non-existant variable you meant to be global; in coffeescript you'll get a local varaible and that means subtly buggy code.
- theOnliest 13y agoI think cursork was talking about 'use strict' in Perl; he said that everyone uses it. 'use strict' in JavaScript is much rarer than it is in Perl, at least in my experience.