How to modify local variables from internal functions?

MRAB python at mrabarnett.plus.com
Sat Oct 24 03:43:24 CEST 2009


kj wrote:
> 
> 
> I like Python a lot, and in fact I'm doing most of my scripting in
> Python these days, but one thing that I absolutely *****DETEST*****
> about Python is that it does allow an internal function to modify
> variables in the enclosing local scope.  This willful hobbling of
> internal functions seems to me so perverse and unnecessary that it
> delayed my adoption of Python by about a decade.  Just thinking
> about it brings me to the brink of blowing a gasket...  I must go
> for a walk...
> 
> 
> 
> OK, I'm better now.
> 
> Anyway, I recently wanted to write a internal helper function that
> updates an internal list and returns True if, after this update,
> the list is empty, and once more I bumped against this hated
> "feature".  What I wanted to write, if Python did what I wanted it
> to, was this:
> 
> def spam():
>     jobs = None 
>     def check_finished(): 
>        jobs = look_for_more_jobs()
>        return not jobs
> 
>     if check_finished():
>         return 
> 
>     process1(jobs)
> 
>     if check_finished():
>         return
> 
>     process2(jobs)
> 
>     if check_finished():
>         return
> 
>     process3(jobs)
> 
> In application in question, the availability of jobs can change
> significantly over the course of the function's execution (jobs
> can expire before they are fully processed, and new ones can arise),
> hence the update-and-check prior to the calls to process1, process2,
> process3.
> 
> But, of course, the above does not work in Python, because the jobs
> variable local to spam does not get updated by check_finished.
> Grrrr!
> 
So you didn't try this?

def spam():
     jobs = []

     def check_finished():
         jobs[:] = look_for_more_jobs()
         return not jobs

     if check_finished():
         return

     process1(jobs)

     if check_finished():
         return

     process2(jobs)

     if check_finished():
         return

     process3(jobs)


Actually, I'd refactor and reduce it to this:

def spam():
     for proc in [process1, process2, process3]:
         jobs = look_for_more_jobs()
         if not jobs:
             return
         proc(jobs)




More information about the Python-list mailing list