classification
Title: recursion wierdness ... related to variable scoping?
Type: behavior Stage:
Components: Interpreter Core Versions: Python 2.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: mark.dickinson, mrdiskodave
Priority: normal Keywords:

Created on 2009-09-16 15:38 by mrdiskodave, last changed 2009-09-16 22:58 by mrdiskodave. This issue is now closed.

Files
File name Uploaded Description Edit
btree.py mrdiskodave, 2009-09-16 15:38 a program that seems to show a python problem (see comment)
Messages (4)
msg92691 - (view) Author: David Hanney (mrdiskodave) Date: 2009-09-16 15:38
I was playing about with ideas behind b-plus-trees
and found i python bug

the important bit of code is:

            


            for p, k in enumerate(self.keys):
                self.ptrs[p].dump(indent+1, kmin=lk, kmax=k)
                print sindent + "(" + str(k) + ")"
                lk = k

            #
            # python bug?
            #
            show_python_bug = len(sys.argv)>1
            if show_python_bug:
                #
                # why not this?
                assert p == len(self.keys)-1
            else:
                #
                # why do I need this instead?
                p = len(self.keys)-1


i'm expecting k to still be in scope and equal len(self.keys)-1
sometimes it is and sometimes it isn't (depending on recursion depth)

you can try it for yourselves as I attach the full program:

./btree.py
runs fine
./btree.py  show_python_bug
eventually breaks like this:

Traceback (most recent call last):
  File "./btree.py", line 235, in <module>
    page.dump()
  File "./btree.py", line 223, in dump
    self.ptrs[p+1].dump(indent+1, kmin=lk)
  File "./btree.py", line 223, in dump
    self.ptrs[p+1].dump(indent+1, kmin=lk)
  File "./btree.py", line 223, in dump
    self.ptrs[p+1].dump(indent+1, kmin=lk)
  File "./btree.py", line 217, in dump
    assert p == len(self.keys)-1
UnboundLocalError: local variable 'p' referenced before assignment

... despite executing that code many times successfully before this
happens ... strange!

I hope you can figure it out and that this report proves helpful.
msg92706 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-16 18:12
This is almost certainly not a bug in Python.  At a guess, in the 
outermost 'else' clause of your dump method, self.keys can be empty.  Then 
the 'for p, k in enumerate(self.keys):' does zero iterations, so p is not 
defined in the assert;  hence the error message.

If you want help figuring out exactly what's going wrong, I'd suggest 
asking on comp.lang.python.
msg92707 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-09-16 18:22
Ah, I see the problem now:  you're expecting that after

for p, elt in enumerate(mylist):
    <do_stuff>

p will be equal to len(mylist)-1.  That's true if mylist is nonempty 
(because on the last round of the for loop, p gets the value len(mylist)-
1), but if mylist is empty then no assignment to p or to elt is ever made.  
That's just the way that Python for loops work, I'm afraid.  :-)
msg92729 - (view) Author: David Hanney (mrdiskodave) Date: 2009-09-16 22:58
Ooops. I'm just learning Python and it never occurred to me that I could
get through the for without k begin defined. At least not until about an
hour ago in the cinema. I came here ASAP but you'd already got to it.
Sorry for wasting your time.

I should have spent more time boiling down a concise test case then I
could have seen this for myself BEFORE posting. Once again, apologies.
History
Date User Action Args
2009-09-16 22:58:51mrdiskodavesetmessages: + msg92729
2009-09-16 18:22:38mark.dickinsonsetmessages: + msg92707
2009-09-16 18:12:21mark.dickinsonsetstatus: open -> closed

nosy: + mark.dickinson
messages: + msg92706

resolution: not a bug
2009-09-16 15:38:42mrdiskodavecreate