default value in __init__
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Fri Oct 17 07:56:07 EDT 2008
On Fri, 17 Oct 2008 23:04:52 +1300, Lawrence D'Oliveiro wrote:
> In message <Xns9B33BC4CC1480duncanbooth at 127.0.0.1>, Duncan Booth wrote:
>
>> We already get people asking why code like this doesn't return 3:
>>
>>>>> fns = [ lambda: x for x in range(10) ] fns[3]()
>> 9
>>
>> ... making this change to default arguments would mean the solution
>> usually proposed to the function scoping question above would no longer
>> work:
>>
>>>>> fns = [ lambda y=x: y for x in range(10) ] fns[3]()
>> 3
>
> The right solution, of course, is
>
> fns = [(lambda x : lambda : x)(x) for x in range(10)]
Only if by "right solution" you mean "excessively verbose, confusing, and
the sort of thing that makes even supporters of lambda cringe".
Yes yes, it's just a factory function written with lambdas. It's still
ugly and exactly the sort of thing that gives ammunition to lambda-
haters. Unlike the solution given by Duncan, which is understandable to
any newbie who has learned about default values and lambda, your solution
requires an understanding of higher-level functions (functions that
return functions, for anyone who doesn't recognise the term) that most
newbies won't have.
And while I don't much care for premature optimization, I will point out
that creating a factory function just to call it once then throw it away
is very wasteful, and that waste is demonstrated by the running time
being more than double that of Duncan's solution:
>>> timeit.Timer('[ lambda y=x: y for x in range(10) ]').repeat()
[7.6332600116729736, 6.9825620651245117, 7.0891578197479248]
>>> timeit.Timer('[(lambda x : lambda : x)(x) for x in range(10)]').repeat()
[18.984915971755981, 17.808281898498535, 18.432481050491333]
--
Steven
More information about the Python-list
mailing list