
On 6/13/2011 3:11 AM, Steven D'Aprano wrote:
Terry Reedy wrote:
Or use closures, which were partly designed to replace default arg use.
Default args are specifically used in at least one use-case where closures give the wrong result.
I meant an explicit user-defined closure with a separate cell for each function ...
funcs = [lambda x: x+i for i in range(10)] funcs[0].__closure__ # may be different in Python 2.x (<cell at 0xb7bd8a1c: int object at 0x81b20c0>,) funcs[0](42) # should return 42+0 51
not this implicit one where each function uses the *same* cell referring to the same int object.
funcs[0].__closure__ (<cell at 0x00FE0330: int object at 0x1E2139A0>,) funcs[9].__closure__ (<cell at 0x00FE0330: int object at 0x1E2139A0>,)
The fundamental problem with this code for funcs is that "lambda x: x+i" is a *constant* equivalent to "def _(x): return x+i". Executing either 10 times creates 10 duplicate functions. The hypnotic effect of 'lambda' is that some do not immediately see the equivalence.
The usual solution is to *not* use a closure:
funcs = [lambda x, i=i: x+i for i in range(10)] funcs[0].__closure__ is None True funcs[0](42) 42 funcs[9](42) 51
The explicit closure solution intended to replace "lambda x,i=i:x+i" is
def makef(j): return lambda x: x+j
funcs = [makef(i) for i in range(10)] list(funcs[_](42) for _ in range(10)) [42, 43, 44, 45, 46, 47, 48, 49, 50, 51] funcs[0].__closure__ (<cell at 0x00FCB4D0: int object at 0x1E213910>,) funcs[9].__closure__ (<cell at 0x00FE0750: int object at 0x1E2139A0>,)
We now have difference cells containing different ints. To get different functions from multiple compilations of one body we need either different defaults for pseudo-parameters or different closure cells. The rationale for adding the latter was partly to be an alternative to the former. Once closure cells were made writable with 'nonlocal', they gained additional uses, or rather, replaced the awkward hack of using mutable 1-element lists as closure contents, with the one elements being the true desired content. -- Terry Jan Reedy