How can I do this (from Perl) in Python? (closures)

Carl Banks pavlovevidence at gmail.com
Thu Dec 4 00:29:17 EST 2008


On Dec 3, 11:18 pm, excor... at gmail.com wrote:
> I just came acrosshttp://www.perl.com/pub/a/2002/05/29/closure.html
> and wanted to try the "canonical example of closures" in Python. I
> came up with the following, but it fails:
>
> #######################
> #!/usr/bin/env python
>
> def make_counter(start_num):
>     start = start_num
>     def counter():
>         start += 1
>     return counter
>
> from_ten = make_counter(10)
> from_three = make_counter(3)
>
> print from_ten()       # 10
> print from_ten()       # 11
> print from_three()     # 3
> print from_ten()       # 12
> print from_three()     # 4
> ####################
>
> The error message is: "UnboundLocalError: local variable 'start'
> referenced before assignment". The same thing happens if I omit start
> and just use start_num directly.
>
> How can I do it in Python?

In Python 3.0, you can do this:

def make_counter(start):
    def counter():
        nonlocal start
        start += 1
        return start # I assume you forgot this above
    return counter


In Python 2.x, there is no nonlocal statement, so the best you can do
is improvise something like this:

def make_counter(start_num):
    start = [start_num]
    def counter():
        start[0] += 1
        return start[0]
    return counter

You can access variables from an enclosing scope starting from Python
2.2 (from 2.1 with from __future__ import nested_scopes), but you
could not rebind those variables until Python 3.0 came out today.


Carl Banks



More information about the Python-list mailing list