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