On Sun, 09 Oct 2005 14:27:32 +0200, Fredrik Lundh wrote: > Steven D'Aprano wrote: > >> Yes I did. Did you read my post? > > given that the wikipedia page says > > "a closure is an abstraction representing a function, plus the > lexical environment (see static scoping) in which the function > was created." > > and you're still focussing on type(function), it sure looks as if you missed > certain parts of that explanation. > > let's take it again, with emphasis on some important words: > > "a closure is an ABSTRACTION representing a function, PLUS the > lexical ENVIRONMENT (see static scoping) in which the function > was created." > >> If you create a closure, using a memoization technique as per the original >> post, and then call type() on that closure, Python reports <type 'function'>. > > that's because "closure" is an abstract concept.
So are functions, modules, classes, instances, ints and strings. > there is no "closure" object > in Python, just as there is no "program" object. Clearly there is no DISTINCT closure object. If there were, I wouldn't need to ask how one can tell them apart, because type() would just report that one was a function and one was a closure. I don't have a problem with that. But read on... > function objects always con- > tain all the information they need about their context, and the sum of that is > what forms the closure. 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. 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:- >>> def closefy(fn): ... def do_nothing(*args, **kwargs): ... return fn(*args, **kwargs) ... return do_nothing ... >>> def spam1(): ... return 0 ... >>> spam2 = closefy(spam1) >>> spam1() 0 >>> spam2() 0 >>> spam2 is spam1 False >>> spam1.func_closure is None True >>> spam2.func_closure (<cell at 0xf70a2734: function object at 0xf6e0a144>,) >>> hex(id(spam1)) '0xf6e0a144' In one case, the "raw" function has None stored in its func_closure attribute. In the other, it has a tuple containing at least one object of type cell. That cell object appears to contain a reference back to the original "raw" function. Now, I'll tell you what I think is going on: spam1() obviously has lexical scope, but that scope doesn't need to be saved with the function because it is implicitly understood by Python. The output of closefy(), on the other hand, has scope different from the "normal" Python scope. So its output has to package up enough information to re-create it's lexical scope in a cell object, and that gets stored in the output's func_closure attribute. So no, there is no "abstract" difference between a closure and a raw function, but there is a practical difference. Now perhaps in some other languages there is no practical difference either, but (as far as I can see) Python is not that language. Am I close? Here are another two code snippets that show something of what Python is doing:- >>> def thingo(): ... def shrubbery(): ... return 0 ... return shrubbery ... >>> spam3 = thingo() >>> spam3() 0 >>> spam3.func_closure is None True >>> def thingy(): ... n = 0 ... def shrubbery(): ... return n ... return shrubbery ... >>> spam4 = thingy() >>> spam4.func_closure (<cell at 0xf70a2b24: int object at 0x901a158>,) -- Steven. -- http://mail.python.org/mailman/listinfo/python-list