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