closure = decorator?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Oct 11 05:24:46 EDT 2013


On Fri, 11 Oct 2013 10:14:29 +0300, Jussi Piitulainen wrote:

> Roy Smith writes:
>> In article <m2a9ihxf3a.fsf at cochabamba.vanoostrum.org>,
>>  Piet van Oostrum wrote:
>> 
>> > I usually say that a closure is a package, containing a function with
>> > some additional data it needs. The data usually is in the form of
>> > name bindings.
>> 
>> That's pretty close to the way I think about it.  The way it was
>> originally described to me is, "A closure is a function bundled up with
>> it's arguments".
> 
> Really? It should be more like "a function bundled up with some other
> function's arguments" and even more like "a function bundled up with
> bindings for its free variables".

Closures have nothing to do with *arguments*. A better definition of a 
closure is that it is a function together with a snapshot of the 
environment it was called from.

def func(arg):
    y = arg + 1
    def inner():
        return y + 1000
    return inner

f = func(1)

At this point, f is a closure. It needs to know the value of y (not the 
argument to func) in order to work, and the implementation is to store 
that information inside f.func_closure (or f.__closure__ in Python 3). 
The part of the calling environment which is saved is y:

py> f.func_closure[0].cell_contents
2


> And the data that makes a function a closure is bindings always, by
> definition, not just usually.

Its not just *any* bindings though, it is specifically bindings to 
variables in the environment from which it was called.


[...]
>> That's a closure.
> 
> I fail to see a closure here. I see a class. I see an implied object
> that could as well be dict(spot=37, time=5). Other entities (garage and
> attendants) are not made sufficiently explicit.

In general, anything you can do with a closure, you can do with an object 
explicitly recording whatever state you want. A closure is just one 
implementation of "callable object with state that can be set when you 
create it". The closure f defined above could instead be written as:

class Func:
    def __init__(self, arg):
        self.y = arg + 1
    def __call__(self):
        return self.y + 1000

f = Func(1)


Which is better? If you want to expose the value of y to the outside 
world to modify, the class solution is better. If you don't, the closure 
is better. Closures tend to be more compact, and I suspect more 
efficient, but there's nothing you can do with one you can't do with the 
other.



-- 
Steven



More information about the Python-list mailing list