Function decorator that caches function results

Steven D'Aprano steve at
Sun Oct 9 20:06:51 CEST 2005

On Sun, 09 Oct 2005 17:55:16 +0200, Diez B. Roggisch wrote:

>> If what you say is true, then all functions are closures, and closure is
>> just a synonym for function, and there is no difference between a function
>> and a closure. Then why bother to create the term? Clearly, whoever
>> invented the term did so to distinguish the two.
> You seem to still not getting to it: they aren't supposed to be 
> distinguished - a function is a function. But it _can_ have a closure, 
> which (shortly spoken) enriches it's local variables lookup. 

[penny drops] Now we're getting somewhere... a closure is something
_added_ to a function. So we should talk about functions-without-closures
and functions-with-closures.

> Speaking in 
> terms of "is a" could be seen as some inheritance relation. 

[penny rises again] Dammit, just when I thought I got it. So a closure is
like a subclass of function? Functions are a higher level classification,
like mammals. There are mammals that are primates (functions that _are_
closures) and mammals that aren't (functions that _aren't_ closures).

> Which 
> functions and functions with a closure _could_ have if one wanted to. 
> But that is true for other OO-concepts two. See below.
>> At a practical, Python level, there is a difference between a function
>> before and after it gets made into a closure using, e.g. the original
>> poster's memoization technique. In Python at least, it is not true that a
>> function and a function-turned-into-closure is the same thing.
>> See, for example, this:-
> <snip>
> Nope. You mix things here. spam1 is a function. 


> spam2 is actually bound 
> to the function-object created by do_nothing - 


> a function that has a closure because it is nested in closefy, and
> accesses variables from its outer lexical scope - thus i needs a
> closure. 

Right! So closures are something which functions _have_ -- which is why
Python functions have an attribute called func_closure, which is empty in
functions without closures, and contain a tuple of cells in those with

Now somebody is going to tell me this is an implementation detail and it
isn't true in the general language independent case...

> Part of do_nothing's closure is spam1 (or, better to say, the
> function reference that has been originally bound to spam1 - spam1 is
> just a name). 

Yes, I can see that.

> Important is that the closure gets created at runtime, so
> each returned instance of do_nothing has its own. But the original spam1
> implementation is untouched  contrary to what  you state above. It still
> is teh same thing, and has no closure.
> Consider this:
> class Foo(object):
>      pass
> f = Foo()
> g = Foo()
> = "whatever"
> f and g are both Foo

Now you're trying to trick me... they are both *instances* of Foo, not
Foo. Foo is a class, and f and g are not classes, let alone the same class.

> - but one has a different attribute set. And if Foo
> had some semantics that did something different based on bar, would you
> also say they're supposed have two different classes? You could in fact
> do that - create one class for each incarnation of possible  state. But
> then the concept of classes and objects gets somewhat blurred, as each
> instance would have its own class. The same is true for functions.

Ah, but in languages like Pascal that can take functions as arguments, but
can't return functions as output, *all* functions have to be created
separately. To take your analogy and run with it, Pascal would be like a
language that didn't allow f and g to have different attributes unless
they belonged to different classes.

Python is not like that, which is why you can write a function to return
functions (a factory function?). If the output function needs access to
the namespace of the factory function, Python adds a closure to that
output function, giving it access to the objects in that namespace.


More information about the Python-list mailing list