[Python-Dev] replacing 'global'

Alex Martelli aleaxit at yahoo.com
Mon Oct 27 11:20:10 EST 2003

On Monday 27 October 2003 04:11 pm, Guido van Rossum wrote:
> I don't think you'll ever *have* to explain this anyway, as long as :=
> and += use the same rules to find their target (I'd even accept

Actually, I'd like to make a := ... an error when there's an a = ... in
the same function, so it can't be exactly the same rules for a += ...
in my opinion.

> I'm *not* saying that I like := (so far I still like 'global x in f'

Ah well.

> I think the main weakness (for me) of := and other approaches that try
> to force you to say you're rebinding a nonlocal each time you do it is
> beginning to show: there are already well-established rules for
> deciding whether a bare name is local or not, and those rules have

There are, but they represent a wart (according to AMK's python-warts
page, http://www.amk.ca/python/writing/warts.html , and I agree with him
on this, although NOT with his suggested fix of having the compiler 
"automatically adding a global when needed" -- I don't like too-clever
compilers that make subtle inferences behind my back, and I think that
the fact that Python's compiler doesn't is a strength, not a weakness).

The "well-established rules" also cause one of the "10 Python pitfalls"
listed at http://zephyrfalcon.org/labs/python_pitfalls.html .  My personal
experience teaching/consulting/mentoring confirms this, although I,
personally, don't remember having been bitten by this (but then, I
recall only 2 of those 10 pitfalls as giving trouble to me personally, as
opposed to people I taught/advised/etc: mutable default arguments,
and "loops of x=x+y" performance traps for sequences).

It seemed to me that introducing := (or other approaches that require
explicit denotation of "I'm binding a nonlocal here") was a chance to
FIX the warts/pitfalls of those "already well-established rules".  Albeit
with a heavy heart, I would consider even a Rubyesque stropping of
nonlocals (Ruby uses $foo to mean foo is nonlocal, others here have
suggested :foo, whatever, it's not the sugar that matters most to me
here) preferable to using "declarative statements" for the purpose.
Oh well.

> always worked "at a distance".  The main reason for disallowing
> rebinding nonlocals in the past has been that one of those rules was
> "if there's a bare-name assignment to it it must be local (unless
> there's also a global statement for it)" (and I couldn't find a
> satisfactory way to add a nonlocal declarative statement and I didn't
> think it was a huge miss -- actually I still think it's not a *huge*
> miss).

Agreed, not huge, just probably marginally worth doing.  Should it
make "declarative statements" more popular and widely used than
today's bare "global", I don't even know if it would be worth it.

I don't like declarative statements.  I don't understand why you
like them here, when, in your message of Thursday 23 October 
2003 06:25:49 on "accumulator display syntax", you condemned
a proposal "because it feels very strongly like a directive to the
compiler".  "A directive to the compiler" is exactly how "global"
and other proposed declarative-statements feel to me: statements
that don't DO things (like all other statements do), but strictly
and only are "like a directive to the compiler".

> > and it doesn't seem to me that the two extra keystrokes are to
> > be considered a substantial price to pay.
> That's the argument that has always been used against += by people who
> don't like it.  The counterargument is that (a) the savings in typing
> isn't always that small, and (b) += *expresses the programmer's

The saving in typing is not always small _when on the left of the
augmented assignment operator you have something much more
complicated than just a bare name_.  For example,

    counter[current_row + current_column * delta] += current_value

Without += this statement would be too long, and it would be
hard to check that the LHS and RHS match exactly -- in practice
one would end up breaking it in two,

    current_index = current_row + current_column * delta
    counter[current_index] = counter[current_index] + current_value

which IS still substantially more cumbersome than the previous
version using += .  But this counterargument does not apply
to uses of += on bare names: the saving is strictly limited to
the length of the bare name, which should be reasonably small.

> thought better*.  Personally I expect that as soon as nonlocal
> rebinding is supported in any way, people would be hugely surprised if
> += and friends were not.

We could try an opinion poll, but it's probably worth it only if this
measure of "expected surprise" was the key point for your decision;
if you're going to prefer declarative statements anyway, there's no
point going through the aggravation.

> > If we do rely on augmented assignment being "rebinding":
> >
> > def accumulator_saturating(n=0, m=100):
> >     def increment(i):
> >         if n > m:
> >             n = i
> >         else:
> >             n += i
> >         return n
> >     return increment
> >
> > the error becomes a runtime rather than compile-time one,
> > and does take a (small but non-zero) time to discover it.
> Hah.  Another argument *against* rebinding by :=, and *for* a nonlocal
> declaration.  With 'nonlocal n, m' in increment() (or however it's
> spelled :-) the intent is clear.

I disagree that the example is "an argument for declarations":
on the contrary, it's an argument for := without "rebinding +=".

The erroneous example just reposted gives a runtime error anyway
(I don't know why I wrote it would give a compile-time error --
just like a bare "def f(): x+=1" doesn't give a compile-time error
today, so, presumably, wouldn't this reposted example).  If
"n := n + i" WAS used in lieu of the augmented assignment,
THEN -- and only then -- could we give the preferable compile-
time error, for forbidden mixing of "n = ..." and "n := ..." in
different spots in the same function.


More information about the Python-Dev mailing list