Re: [Python-Dev] more timely detection of unbound locals

2011-05-15 Thread Vinay Sajip
Terry Reedy  udel.edu> writes:

> I would change this to
> "local name 'bob' used before the assignment that makes it a local name"
> 
> Calling names 'variables' is itself a point of confusion.

+1


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Fred Drake
On Tue, May 10, 2011 at 6:38 PM, Steven D'Aprano  wrote:
> I don't know why it was thought necessary to distinguish between them in the
> first place.

New users almost constantly expressed confusion by NameError when the name
was clearly bound at global scope, and a subsequent assignment caused it to be
considered a local in their function.


  -Fred

-- 
Fred L. Drake, Jr.    
"Give me the luxuries of life and I will willingly do without the necessities."
   --Frank Lloyd Wright
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Steven D'Aprano

Nick Coghlan wrote:


Personally, I would just add "in current scope" to the existing error
message for the unbound local case (and potentially collapse the
exception hierarchy a bit by setting UnboundLocalError = NameError).


-0

That was the case prior to Python 2.0. Reverting is potentially a 
semantic change that will break any code that distinguishes between 
(global) NameError and (local) UnboundLocalError. But personally, I 
don't know why it was thought necessary to distinguish between them in 
the first place.





--
Steven
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Eli Bendersky


> > > # Early reference to local
> > > UnboundLocalError: local variable 'bob' referenced before assignment
> >
> > I would change this to
> > "local name 'bob' used before the assignment that makes it a local name"
> >
> > Calling names 'variables' is itself a point of confusion.
>
> Yes, your phrasing is much better.
>

+1
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread R. David Murray
On Tue, 10 May 2011 13:56:58 -0400, Terry Reedy  wrote:
> On 5/10/2011 10:59 AM, Nick Coghlan wrote:
> > On Tue, May 10, 2011 at 11:11 PM, R. David Murray  
> > wrote:
> >> How about:
> >>
> >> "reference to variable 'y' precedes an assignment that makes it a local
> >> variable"
> >
> > For comparison, the error messages I was able to elicit from 2.7 were
> > as follows:
> >
> > # Module level
> > NameError: name 'bob' is not defined
> >
> > # Function level reference to implicit global
> > NameError: global name 'bob' is not defined
> >
> > # Early reference to local
> > UnboundLocalError: local variable 'bob' referenced before assignment
> 
> I would change this to
> "local name 'bob' used before the assignment that makes it a local name"
> 
> Calling names 'variables' is itself a point of confusion.

Yes, your phrasing is much better.

--
R. David Murray   http://www.bitdance.com
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Terry Reedy

On 5/10/2011 10:59 AM, Nick Coghlan wrote:

On Tue, May 10, 2011 at 11:11 PM, R. David Murray  wrote:

How about:

"reference to variable 'y' precedes an assignment that makes it a local
variable"


For comparison, the error messages I was able to elicit from 2.7 were
as follows:

# Module level
NameError: name 'bob' is not defined

# Function level reference to implicit global
NameError: global name 'bob' is not defined

# Early reference to local
UnboundLocalError: local variable 'bob' referenced before assignment


I would change this to
"local name 'bob' used before the assignment that makes it a local name"

Calling names 'variables' is itself a point of confusion.


# Early reference from closure
NameError: free variable 'bob' referenced before assignment in enclosing scope

Personally, I would just add "in current scope" to the existing error
message for the unbound local case (and potentially collapse the
exception hierarchy a bit by setting UnboundLocalError = NameError).

Cheers,
Nick.




--
Terry Jan Reedy

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread R. David Murray
On Wed, 11 May 2011 00:59:08 +1000, Nick Coghlan  wrote:
> On Tue, May 10, 2011 at 11:11 PM, R. David Murray  w=
> rote:
> > How about:
> >
> > "reference to variable 'y' precedes an assignment that makes it a local
> > variable"
> 
> For comparison, the error messages I was able to elicit from 2.7 were
> as follows:
> 
> # Module level
> NameError: name 'bob' is not defined
> 
> # Function level reference to implicit global
> NameError: global name 'bob' is not defined
> 
> # Early reference to local
> UnboundLocalError: local variable 'bob' referenced before assignment
> 
> # Early reference from closure
> NameError: free variable 'bob' referenced before assignment in enclosing sc=
> ope
> 
> Personally, I would just add "in current scope" to the existing error
> message for the unbound local case (and potentially collapse the
> exception hierarchy a bit by setting UnboundLocalError = NameError).

I don't think adding that phrase would add any clarity, myself.
The mental disconnect comes from the fact that the UnboundLocal error
message is emitted for the reference, but it is not immediately obvious
*why* the variable is considered local.  My rephrasing emphasizes that it
is the assignment statement that led to that classification and therefore
the error.  This disconnect doesn't apply in the global cases.  It applies
less strongly in the free variable case because there is visibly another
scope involved (that is, the triggering assignment isn't in the same
scope as the reference producing the error message).

--
R. David Murray   http://www.bitdance.com
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Nick Coghlan
On Tue, May 10, 2011 at 11:11 PM, R. David Murray  wrote:
> How about:
>
> "reference to variable 'y' precedes an assignment that makes it a local
> variable"

For comparison, the error messages I was able to elicit from 2.7 were
as follows:

# Module level
NameError: name 'bob' is not defined

# Function level reference to implicit global
NameError: global name 'bob' is not defined

# Early reference to local
UnboundLocalError: local variable 'bob' referenced before assignment

# Early reference from closure
NameError: free variable 'bob' referenced before assignment in enclosing scope

Personally, I would just add "in current scope" to the existing error
message for the unbound local case (and potentially collapse the
exception hierarchy a bit by setting UnboundLocalError = NameError).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread Eli Bendersky
On Tue, May 10, 2011 at 16:11, R. David Murray wrote:

> On Tue, 10 May 2011 08:36:38 +0300, Eli Bendersky 
> wrote:
> > With an unlimited error message length it could make sense to say "Hey, I
> > see 'x' may be assigned in this scope, so I mark it local. But this
> access
> > to 'x' happens before assignment - so ERROR". This isn't realistic, of
> > course, so I'm wondering:
> >
> > 1. Does this error message (although unrealistic) capture all possible
> > appearances of UnboundLocalError?
> > 2. If the answer to (1) is yes - could it be usefully shortened to be
> > clearer than the current "local variable referenced before assignment"?
> >
> > This may not be possible, of course, but it doesn't harm trying :-)
>
> How about:
>
> "reference to variable 'y' precedes an assignment that makes it a local
> variable"
>  


Yes, this is much better and not too long IMHO
Eli
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-10 Thread R. David Murray
On Tue, 10 May 2011 08:36:38 +0300, Eli Bendersky  wrote:
> With an unlimited error message length it could make sense to say "Hey, I
> see 'x' may be assigned in this scope, so I mark it local. But this access
> to 'x' happens before assignment - so ERROR". This isn't realistic, of
> course, so I'm wondering:
> 
> 1. Does this error message (although unrealistic) capture all possible
> appearances of UnboundLocalError?
> 2. If the answer to (1) is yes - could it be usefully shortened to be
> clearer than the current "local variable referenced before assignment"?
> 
> This may not be possible, of course, but it doesn't harm trying :-)

How about:

"reference to variable 'y' precedes an assignment that makes it a local
variable"

IMO this still leaves room for confusion, but is better because it
indicates the causation more clearly.  (I don't think it is necessary to
capture the subtlety of conditional assignment in the error message.)

--
R. David Murray   http://www.bitdance.com
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Stefan Behnel

[forwarded to the python-ideas list]

Stefan

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Eli Bendersky
On Mon, May 9, 2011 at 18:44, Isaac Morland  wrote:

> On Mon, 9 May 2011, Eli Bendersky wrote:
>
>  x = 5
>>> def foo ():
>>>   print (x)
>>>   if bar ():
>>>   x = 1
>>>   print (x)
>>>
>>>
>> I wish you'd annotate this code sample, what do you intend it to
>> demonstrate?
>>
>> It probably shows the original complaint even more strongly. As for being
>> a
>> problem with the suggested solution, I suppose you're right, although it
>> doesn't make it much different. Still, before a *possible* assignment to
>> 'x', it should be loaded as LOAD_NAME since it was surely not bound as
>> local, yet.
>>
>
> Extrapolating from your suggestion, you're saying before a *possible*
> assignment it will be treated as global, and after a *possible* assignment
> it will be treated as local?
>
> But surely:
>
> print (x)
> if False:
>x = 1
> print (x)
>
> [snip]

Alright, I now understand the problems with the suggestion. Indeed,
conditional assignments that are only really resolved at runtime are the big
stumbling block here.

However, maybe the error message/reporting can still be improved?

ISTM the UnboundLocalError exception gets raised only in those weird and
confusing cases. After all, why would Python decide an access to some name
is to a local? Only if it found an assignment to that local in the scope.
But that assignment clearly didn't happen yet, so the error is thrown. So
cases like these:

x = 2

def foo1():
  x += 1

def foo2():
  print(x)
  x = 10

def foo3():
  if something_that_didnot_happen:
x = 10
  print(x)

All belong to the category.

With an unlimited error message length it could make sense to say "Hey, I
see 'x' may be assigned in this scope, so I mark it local. But this access
to 'x' happens before assignment - so ERROR". This isn't realistic, of
course, so I'm wondering:

1. Does this error message (although unrealistic) capture all possible
appearances of UnboundLocalError?
2. If the answer to (1) is yes - could it be usefully shortened to be
clearer than the current "local variable referenced before assignment"?

This may not be possible, of course, but it doesn't harm trying :-)
Eli
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Terry Reedy

On 5/9/2011 9:27 AM, Stefan Behnel wrote:

Eli Bendersky, 09.05.2011 14:56:

It's a known Python gotcha (*) that the following code:

x = 5
def foo():
print(x)
x = 1
print(x)
foo()

Will throw:

UnboundLocalError: local variable 'x' referenced before assignment

On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an
implementation
artifact.


Well, basically any compiler these days can detect that a variable is
being used before assignment, or at least that this is possibly the
case, depending on prior branching.

ISTM that your suggestion is to let x refer to the outer x up to the
assignment and to the inner x from that point on. IMHO, that's much
worse than the current behaviour and potentially impractical due to
conditional assignments.

However, it's also a semantic change to reject code with unbound locals
at compile time, as the specific code in question may actually be
unreachable at runtime. This makes me think that it would be best to
discuss this on the python-ideas list first.

If nothing else, I'd like to see a discussion on this behaviour being an
implementation detail of CPython or a feature of the Python language.

Stefan




--
Terry Jan Reedy

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Steven D'Aprano

Eli Bendersky wrote:

I think you are making an unwarranted assumption about what is "more
expected". I presume you are thinking that the expected behaviour is that
foo() should:

print global x (5)
assign 1 to local x
print local x (1)

If we implemented this change, there would be no more questions about
UnboundLocalError, but instead there would be lots of questions like "why is
it that globals revert to their old value after I change them in a
function?".



True, but this is less confusing and follows the rules in a more
straightforward way. x = 1 without a 'global x' assigns a local x, this make
sense and is similar to what happens in C where an inner declaration
temporarily shadows a global one.


I disagree that it is less confusing. Instead of a nice, straightforward 
error that you can google, the function will silently do the wrong 
thing, giving no clue that weirdness is happening.


def spam():
if x < 0:  # refers to global x
x = 1  # now local
if x > 0:  # could be either global or local
x = x - 1  # local on the LHS of the equal
# sometimes global on the RHS
else:
x += 1  # local x, but what value does it have?


Just thinking about debugging the mess that this could make gives me a 
headache.




--
Steven

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Isaac Morland

On Mon, 9 May 2011, Eli Bendersky wrote:


x = 5
def foo ():
   print (x)
   if bar ():
   x = 1
   print (x)



I wish you'd annotate this code sample, what do you intend it to
demonstrate?

It probably shows the original complaint even more strongly. As for being a
problem with the suggested solution, I suppose you're right, although it
doesn't make it much different. Still, before a *possible* assignment to
'x', it should be loaded as LOAD_NAME since it was surely not bound as
local, yet.


Extrapolating from your suggestion, you're saying before a *possible* 
assignment it will be treated as global, and after a *possible* assignment 
it will be treated as local?


But surely:

print (x)
if False:
x = 1
print (x)

should always print the same thing twice (in the absence of actions taken 
by other threads)!


Replace "False" by something that is usually (but not always) True, and 
"print (x)" by something that actually does something, and you had best 
put on your helmet because it's going to be a fun ride.


But I won't be on it.

The idea that the same name within the same scope always refers to the 
same value is an idea from functional programming and not part of Python; 
but surely the same name within the same scope should at least always 
refer to the same variable!


If something is to be done here, it occurs to me that the same parser that 
decides that the initial reference to x should use the local x could 
conceivably issue an error right away - "local variable can never be 
assigned before use" rather than waiting until runtime.  But even if I 
haven't confused myself about the possibility of this raising a false 
positive (and it certainly could in the presence of dead code), it 
wouldn't catch cases of conditional premature use of a local variable. I 
think in those cases people would still ask the same questions they do 
with the existing implementation.


Isaac Morland   CSCF Web Guru
DC 2554C, x36650WWW Software Specialist
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Nick Coghlan
On Tue, May 10, 2011 at 1:06 AM, Eli Bendersky  wrote:
> It probably shows the original complaint even more strongly. As for being a
> problem with the suggested solution, I suppose you're right, although it
> doesn't make it much different. Still, before a *possible* assignment to
> 'x', it should be loaded as LOAD_NAME since it was surely not bound as
> local, yet.

Yeah, I've decided I'm happier with the closure based arguments than
the conditional statement related ones. "Assignments create local
variables" is a relatively simple rule to reason about, and is equally
valid for the current scope and for any nested scopes. The symtable
analysis for nested scopes is ordering independent (and can't be
changed for backwards compatibility reasons if nothing else), and
UnboundLocalError is a natural outgrowth of applying those semantics
to the current scope as well.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Nick Coghlan
On Tue, May 10, 2011 at 1:01 AM, Eli Bendersky  wrote:
>
>> I think you are making an unwarranted assumption about what is "more
>> expected". I presume you are thinking that the expected behaviour is that
>> foo() should:
>>
>> print global x (5)
>> assign 1 to local x
>> print local x (1)
>>
>> If we implemented this change, there would be no more questions about
>> UnboundLocalError, but instead there would be lots of questions like "why is
>> it that globals revert to their old value after I change them in a
>> function?".
>
> True, but this is less confusing and follows the rules in a more
> straightforward way. x = 1 without a 'global x' assigns a local x, this make
> sense and is similar to what happens in C where an inner declaration
> temporarily shadows a global one.

However, since flow control constructs in Python don't create new
scopes (unlike C/C++), you run into a fundamental problem with cases
like the one Isaac posted, or even nastier ones like the following:

def f():
  if bar():
fill = 1
  else:
fiil = 2
  print(fill)  # Q: What does this do when bool(bar()) is False?

Since we want to make the decision categorically at compile-time, the
simplest, least-confusing option is to say "assignment makes a
variable name local, referencing it before the first assignment is now
an error". I don't know of anyone that particularly *likes*
UnboundLocalError, but it's better than letting errors like the one
above pass silently. (It obviously doesn't trap *all* typo-related
errors, but it at least lets you reason sanely about name bindings)

On the reasoning-sanely front, closures likely present a more
compelling argument:

def f():
  def g():
print(x) # We want this to refer to the closure in f(), thanks
  x = 1
  return g

UnboundLocalError is really about aligning the rules for the current
scope with those for references from nested scopes (i.e. x is a local
variable of f, whether it is referenced from f's local scope, or any
nested scope within f)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Eli Bendersky
> x = 5
> def foo ():
>print (x)
>if bar ():
>x = 1
>print (x)
>

I wish you'd annotate this code sample, what do you intend it to
demonstrate?

It probably shows the original complaint even more strongly. As for being a
problem with the suggested solution, I suppose you're right, although it
doesn't make it much different. Still, before a *possible* assignment to
'x', it should be loaded as LOAD_NAME since it was surely not bound as
local, yet.

Eli
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Eli Bendersky
> I think you are making an unwarranted assumption about what is "more
> expected". I presume you are thinking that the expected behaviour is that
> foo() should:
>
> print global x (5)
> assign 1 to local x
> print local x (1)
>
> If we implemented this change, there would be no more questions about
> UnboundLocalError, but instead there would be lots of questions like "why is
> it that globals revert to their old value after I change them in a
> function?".
>

True, but this is less confusing and follows the rules in a more
straightforward way. x = 1 without a 'global x' assigns a local x, this make
sense and is similar to what happens in C where an inner declaration
temporarily shadows a global one.

Eli
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Steven D'Aprano

Eli Bendersky wrote:

Hi all,

It's a known Python gotcha (*) that the following code:

x = 5
def foo():
print(x)
x = 1
print(x)
foo()

Will throw:

   UnboundLocalError: local variable 'x' referenced before assignment


I think part of the problem is that UnboundLocalError is a jargon name, 
while it's predecessor NameError (used up to Python 1.5) is far more 
intuitively obvious.




On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an implementation
artifact.

[...]

Would it not be worth to make Python's behavior more expected in this case,
at the cost of some implementation complexity? What are the cons to making
such a change? At least judging by the amount of people getting confused by
it, maybe it's in line with the zen of Python to behave more explicitly
here.


I think you are making an unwarranted assumption about what is "more 
expected". I presume you are thinking that the expected behaviour is 
that foo() should:


print global x (5)
assign 1 to local x
print local x (1)

If we implemented this change, there would be no more questions about 
UnboundLocalError, but instead there would be lots of questions like 
"why is it that globals revert to their old value after I change them in 
a function?".





--
Steven

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Eric Snow
On May 9, 2011 6:59 AM, "Eli Bendersky"  wrote:
>
> Hi all,
>
> It's a known Python gotcha (*) that the following code:
>
> x = 5
> def foo():
> print(x)
> x = 1
> print(x)
> foo()
>
> Will throw:
>
>UnboundLocalError: local variable 'x' referenced before assignment
>
> On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an implementation
artifact.
>
> IIUC, the reason it behaves this way is that the symbol table logic goes
over the code before the code generation runs, sees the assignment 'x = 1`
and marks 'x' as local in foo. Then, the code generator generates LOAD_FAST
for all loads of  'x' in 'foo', even though 'x' is actually bound locally
after the first print. When the bytecode is run, since it's LOAD_FAST and no
store was made into the local 'x', ceval.c then throws the exception.
>
> On first sight, it's possible to signal that 'x' truly becomes local only
after it's bound in the scope (and before that LOAD_NAME can be generated
for it instead of LOAD_FAST). To do this, some modifications to the symbol
table creation and usage are required, because we can no longer say "x is
local in this block", but rather should attach scope information to each
instance of "x". This has some overhead, but it's only at the compilation
stage so it shouldn't have a real effect on the runtime of Python code. This
is also less convenient and "clean" than the current approach - this is why
I'm wondering whether the behavior is an artifact of the implementation.
>
> Would it not be worth to make Python's behavior more expected in this
case, at the cost of some implementation complexity? What are the cons to
making such a change? At least judging by the amount of people getting
confused by it, maybe it's in line with the zen of Python to behave more
explicitly here.

This is about mixing scopes for the the same name in the same block, right?
Perhaps a more specific error would be enough, unless there is a good use
case for having that mixed scope for the name.

-eric

> Thanks in advance,
> Eli
>
> (*) Variation of this FAQ:
http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
>
>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
http://mail.python.org/mailman/options/python-dev/ericsnowcurrently%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Stefan Behnel

Eli Bendersky, 09.05.2011 14:56:

It's a known Python gotcha (*) that the following code:

x = 5
def foo():
 print(x)
 x = 1
 print(x)
foo()

Will throw:

UnboundLocalError: local variable 'x' referenced before assignment

On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an implementation
artifact.


Well, basically any compiler these days can detect that a variable is being 
used before assignment, or at least that this is possibly the case, 
depending on prior branching.


ISTM that your suggestion is to let x refer to the outer x up to the 
assignment and to the inner x from that point on. IMHO, that's much worse 
than the current behaviour and potentially impractical due to conditional 
assignments.


However, it's also a semantic change to reject code with unbound locals at 
compile time, as the specific code in question may actually be unreachable 
at runtime. This makes me think that it would be best to discuss this on 
the python-ideas list first.


If nothing else, I'd like to see a discussion on this behaviour being an 
implementation detail of CPython or a feature of the Python language.


Stefan

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Isaac Morland

On Mon, 9 May 2011, Eli Bendersky wrote:


It's a known Python gotcha (*) that the following code:

x = 5
def foo():
   print(x)
   x = 1
   print(x)
foo()

Will throw:

  UnboundLocalError: local variable 'x' referenced before assignment

On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an implementation
artifact.

IIUC, the reason it behaves this way is that the symbol table logic goes
over the code before the code generation runs, sees the assignment 'x = 1`
and marks 'x' as local in foo. Then, the code generator generates LOAD_FAST
for all loads of  'x' in 'foo', even though 'x' is actually bound locally
after the first print. When the bytecode is run, since it's LOAD_FAST and no
store was made into the local 'x', ceval.c then throws the exception.

On first sight, it's possible to signal that 'x' truly becomes local only
after it's bound in the scope (and before that LOAD_NAME can be generated
for it instead of LOAD_FAST). To do this, some modifications to the symbol
table creation and usage are required, because we can no longer say "x is
local in this block", but rather should attach scope information to each
instance of "x". This has some overhead, but it's only at the compilation
stage so it shouldn't have a real effect on the runtime of Python code. This
is also less convenient and "clean" than the current approach - this is why
I'm wondering whether the behavior is an artifact of the implementation.


x = 5
def foo ():
print (x)
if bar ():
x = 1
print (x)

Isaac Morland   CSCF Web Guru
DC 2554C, x36650WWW Software Specialist
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] more timely detection of unbound locals

2011-05-09 Thread Eli Bendersky
Hi all,

It's a known Python gotcha (*) that the following code:

x = 5
def foo():
print(x)
x = 1
print(x)
foo()

Will throw:

   UnboundLocalError: local variable 'x' referenced before assignment

On the usage of 'x' in the *first* print. Recently, while reading the
zillionth question on StackOverflow on some variation of this case, I
started thinking whether this behavior is desired or just an implementation
artifact.

IIUC, the reason it behaves this way is that the symbol table logic goes
over the code before the code generation runs, sees the assignment 'x = 1`
and marks 'x' as local in foo. Then, the code generator generates LOAD_FAST
for all loads of  'x' in 'foo', even though 'x' is actually bound locally
after the first print. When the bytecode is run, since it's LOAD_FAST and no
store was made into the local 'x', ceval.c then throws the exception.

On first sight, it's possible to signal that 'x' truly becomes local only
after it's bound in the scope (and before that LOAD_NAME can be generated
for it instead of LOAD_FAST). To do this, some modifications to the symbol
table creation and usage are required, because we can no longer say "x is
local in this block", but rather should attach scope information to each
instance of "x". This has some overhead, but it's only at the compilation
stage so it shouldn't have a real effect on the runtime of Python code. This
is also less convenient and "clean" than the current approach - this is why
I'm wondering whether the behavior is an artifact of the implementation.

Would it not be worth to make Python's behavior more expected in this case,
at the cost of some implementation complexity? What are the cons to making
such a change? At least judging by the amount of people getting confused by
it, maybe it's in line with the zen of Python to behave more explicitly
here.

Thanks in advance,
Eli

(*) Variation of this FAQ:
http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com