On Sat, 09 Oct 2010 19:30:16 -0700, Ethan Furman <et...@stoneleaf.us> wrote: > Steven D'Aprano wrote: [snip] >> But that doesn't mean that the list comp is the general purpose solution. >> Consider the obvious use of the idiom: >> >> def func(arg, count): >> # Initialise the list. >> L = [arg for i in range(count)] >> # Do something with it. >> process(L, some_function) >> >> def process(L, f): >> # Do something with each element. >> for item in enumerate(L): >> f(item) >> >> Looks good, right? But it isn't, because it will suffer the exact same >> surprising behaviour if f modifies the items in place. Using a list comp >> doesn't save you if you don't know what the object is. > > I've only been using Python for a couple years on a part-time basis, so > I am not aquainted with this obvious use -- could you give a more > concrete example? Also, I do not see what the list comp has to do with > the problem in process() -- the list has already been created at that > point, so how is it the list comp's fault?
Well, here's a worked example of Steven D's code (Python 2.5.2): >>> def func(arg, count): ... L = [arg for i in range(count)] ... process(L, some_function) ... >>> def process(L, v): ... for item in L: ... v(item) ... >>> def some_function(x): ... x.append(1) ... print x ... >>> func([], 3) [1] [1, 1] [1, 1, 1] >>> Is that the output you expected? Probably not: the unwary reader (including me, not too long ago) expects that L = [arg for i in range(count)] will be equivalent to L = [[], [], []] but it's not, because the three elements in the first L are three references to the *same* list. Observe: >>> arg = [] >>> L = [arg for i in range(3)] >>> L [[], [], []] >>> L[0].append(1) >>> L [[1], [1], [1]] ... as opposed to ... >>> L = [ [] for i in range(3)] >>> L [[], [], []] >>> L[0].append(1) >>> L [[1], [], []] -- To email me, substitute nowhere->spamcop, invalid->net. -- http://mail.python.org/mailman/listinfo/python-list