Scope in 2.2.1

David LeBlanc whisper at oz.net
Sat May 11 05:38:05 EDT 2002


Alex;

Thanks for your comments.

I am confused by the last part though: you say that "bar2 += 1" is a
reference before a rebinding or alteration of an already bound variable.
Well, bar2 _is_ already bound by the logic you used in the discussion of bar
in the print statement!

What would happen if, instead of "print bar", it said "bar += 1" or "print
bar++"? As python works now, it would seem that "bar += 1 is an error, but
i'm not sure about bar++, since it's a post-fetch increment. It seems
inconsistant to me that a reference (without modification) finds an outer
binding in a print statement, but an implicit (attempt to) reference in a
plus-equals is an error.

It only makes sense to me to not use foo.bar2 within fee() if there's a
local bar2 or a "global bar2" (which would then have to refer to a global
bar2, not foo.bar2 no?). As you say, "+=" is a reference and rebinding (if
that's the appropriate terminology). Since the reference comes before the
rebinding, the nearest pre-existing binding of bar2 ought to be used. I
think this is a bug! I think it at least violates the principle of least
surprise :-)

Maybe the appendix would make more sense as:

"If a name binding operation occurs anywhere within a code block, all uses
of that name within the block are treated as references to that binding.
This will lead to errors when a name is used within a block before it is
bound."

Regards,

David LeBlanc
Seattle, WA USA

> -----Original Message-----
> From: python-list-admin at python.org
> [mailto:python-list-admin at python.org]On Behalf Of Alex Martelli
> Sent: Saturday, May 11, 2002 1:52
> To: python-list at python.org
> Subject: Re: Scope in 2.2.1
>
>
> David LeBlanc wrote:
>
> > The 2.2.1 Python doc in Appendix A1 says:
> > "If a name binding operation occurs anywhere within a code
> block, all uses
> > of the name within the block are treated as references to the current
> > block. This can lead to errors when a name is used within a block before
> > it is bound."
> >
> > def foo():                    #block
> > 	bar = 0               #binding
> >
> > bar now is a reference to foo? Somehow, I doubt that!
>
> Right -- the wording of A1 may not be optimal here.
>
>
> > My other question pertaining to this paragraph is: what errors can occur
> > if a name is used before it's bound?
>
> NameError, or its subclass UnboundLocalError specifically.
>
>
> > My other question is illustrated by this code:
> >
> >>>> def foo():
> > ...     bar = 0
> > ...     bar2 = 0
> > ...     def fee():
> > ...             print bar
> > ...             bar2 += 1
> > ...             print bar2
> > ...     fee()
> > ...
> >>>> foo()
> > 0
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in ?
> >   File "<stdin>", line 8, in foo
> >   File "<stdin>", line 6, in fee
> > UnboundLocalError: local variable 'bar2' referenced before assignment
> >
> > Is the bar in "print bar" the bar of foo(), or is it an unbound bar?
>
> It's "the bar of foo" since the block of fee has no binding operations
> on it so nested local scopes apply.
>
> > Is foo.bar2 the bar2 in fee() or is it a new local fee.bar2?
> The traceback
>
> The bar2 in fee is a local variable of bar2 because the body of fee
> includes the binding operation "bar2 +=".
>
> Actually, all augmented assignments can only ever *RE*-bind their LHS,
> so the compiler might be able to diagnose the error if a block's only
> binding operations on a name are augmented assignments -- in theory.
>
> > implies that the "print bar" statement used foo.bar, yet it blew up on
> > incrementing bar2!
>
> Yes, because bar comes from outer scope (since there is no binding
> operation on it) but bar2 is a local (since there IS a binding op on it).
>
> > (Note: the error reporting seems misleading, since "+="
> > is an assignment no?)
>
> It's an access, "perhaps" followed by an assignment (which is why it
> can only ever re-bind, or alter -- never bind anew a name that was
> not bound before...: because first it must access that name's present
> binding).  The reference (access) is indeed before any assignment.
>
>
> Alex
>
> --
> http://mail.python.org/mailman/listinfo/python-list






More information about the Python-list mailing list