Simplified Shadows of Python

Aug 08, 2016 16:50

I spent longer than I expected figuring out the problem described in Robbie's Shadows of Python post. I kept revising my e-mail to him: "You're wrong because of X. No, I mean Y. Um, Z?" Eventually I got it, I think, and distilled it to a simpler piece of contrasting code:

x=1

def f():
print(x)

def g():
print(x)
x=2

>>> f()
1
>>> g()
Traceback (most recent call last):
File "", line 1, in
File "r.py", line 8, in g
print(x)
UnboundLocalError: local variable 'x' referenced before assignment

Simply because we will (or even might, it works if the assignment is in an if clause) assign to x in the future, it becomes a local variable for the scope of the whole function, blocking access to the outer scope definition. This compile-time annoyance from the same language that has no equivalent to Perl's 'use strict;' to stop you from using misspelled variables. Thanks, Python.

Checking against the other big scripting language, Perl:

$x=1;

sub f {
print $x, "\n";
}
sub g {
print $x, "\n";
$x=2;
}

f();
g();
f();

[Zefiris:0] perl r.pl
1
1
2

Happy access to a global variable. If you use 'my $x=2;' in g(), then the change to the global-level variable is avoided, of course.

Python would let you use 'global x' in g(), or 'nonlocal x' for intermediate scopes, but that gives you full access to x. There's no "I'm going to create a new local variable from this point on, while having used an outer variable earlier in the function." And this doesn't work:

x=1
def h():
x=x
print(x)
h()

You can do that in Perl, with or without 'my', getting expected behavior in each case.

This is part of the reason I'm willing to work in C++ again; yes, it's annoying, but I've seen no language that doesn't have mindbendingly stupid shit in it somewhere.

Edit: someday I'll remember I want the pre tag, not the code tag, for preserving indentation.

See the
DW comments at http://mindstalk.dreamwidth.org/450941.html#comments

python, programming

Previous post Next post
Up