From: Lie Ryan on 6 Jun 2010 15:59 On 06/07/10 05:54, D'Arcy J.M. Cain wrote: > On Mon, 07 Jun 2010 05:27:43 +1000 > Lie Ryan <lie.1296(a)gmail.com> wrote: >> In the most naive uses, map appears to have no advantage over list >> comprehension; but one thing that map can do that list comprehension >> still can't do without a walk around the park: >> >> def foo(func, args): >> g = lambda x: x+1 >> return [func(g, x) for x in args] >> >> foo(map, [[4, 6, 3], [6, 3, 2], [1, 3, 5]]) > > foo = lambda x: [y + 1 for y in x] > [foo(x) for x in [[4, 6, 3], [6, 3, 2], [1, 3, 5]]] > > Didn't seem like such a long walk. > that's because you're simplifying the problem, the correct walk is: def foo(func, args): g = lambda x: x+1 return [func(g, x) for x in args] foo((lambda g, a: [g(x) for x in a]), [[4, 6, 3], [6, 3, 2], [1, 3, 5]])
From: rantingrick on 6 Jun 2010 17:01 On Jun 6, 2:48 pm, Richard Thomas <chards...(a)gmail.com> wrote: > Python's map has the useful feature that nobody is in any doubt about > what it does. I don't know much about Ruby I have to say but looking > at that piece of syntax you gave I had no idea how to interpret it. > Anyway, I looked it up. Well Ruby likes to pass block in the form { ...expression... }. I don't really care for the braces but the map is more natural in Ruby >>> array = [1,2,3].map{|x| x.to_s} >>> array ['1', '2', '3'] >>> array.length 3 >>> 'abc'.map{|x| x.upcase}.join 'ABC' #-- as in python you do the nested thing --# >>> lst = map(str, [1,2,3]) >>> lst ['1', '2', '3'] >>> len(lst) 3 >>> ''.join(map(string.upper, 'abc')) 'ABC' Thats the only thing that bother me about Python. But in Ruby the sky's the limit since you pass a block. And no need for that clunky lambda. I think Guido and Matz need to set down for a cup of joe fire up their interpretors and exchange thoughts about language design. Some awesome synergy could come of it and maybe even create the next best language. Guido can teach Matz about the importance of forced indention over braces, docstrings, command line help, explicitly calling functions/ method, perfect keyword naming, __specialmethodnames__, the Python Zen! And Matz can show Guido how to build a better lambda and map functions and more syntactically correct OOP style. Just ideas folks ;)
From: Terry Reedy on 6 Jun 2010 17:43 On 6/6/2010 11:16 AM, rantingrick wrote: > Everyone knows i'm a Python fanboy so nobody can call me a troll for > this... Non sequitor. It depends on your intention in posting this... > Python map is just completely useless. For one it so damn slow Posting invalid speed comparisons stacked against the feature you are dissing is either trollish or lame. > why even bother putting it in the language? Map was put into the language about a decade before comprehensions and, I believe, zip. It encapsulates a basic functional programming idiom. Consider the following snippet: (in 2.x, delete 'list(' and ...')'): from operator import add l1 = range(10) l2 = range(15,30) print(list(map(add, l1, l2))) # [15, 17, 19, 21, 23, 25, 27, 29, 31, 33] Now replace map with a for loop, no zip or listcomp or genexp allowed. Time how long it takes. Do you get it right the first time, as I did with the above?. Your replacememt may or may not *run* faster, but even if so, it will hardly be enough to make much different in most uses. > Maybe GVR should have taken it out in 3.0? That may have been considered, but map is shorter than the alternative, some prefer it stylistically, it can be passed as a function argument (including to functool.partial), and its removal would have broken code without much gain. It is also handy for explaing generator expressions and comprehensions. Terry Jan Reedy
From: Steven D'Aprano on 6 Jun 2010 19:20 On Sun, 06 Jun 2010 08:16:02 -0700, rantingrick wrote: > Everyone knows i'm a Python fanboy so nobody can call me a troll for > this... The first rule of trolling is, always deny being a troll, no matter how obvious the trolling. But on the chance I'm wrong, and for the benefit of others, your tests don't measure what you think they are measuring and consequently your results are invalid. Read on. > Python map is just completely useless. For one it so damn slow why even > bother putting it in the language? And secondly, the total "girl- man" > weakness of lambda renders it completely mute! Four trolls in three sentences. Way to go "fanboy". (1) "Completely" useless? It can't do *anything*? (2) Slow compared to what? (3) Are you implying that map relies on lambda? (4) What's wrong with lambda anyway? By the way, nice sexist description there. "Girl-man weakness" indeed. Does your mum know that you are so contemptuous about females? > Ruby has a very nice map I'm thrilled for them. Personally I think the syntax is horrible. >>>> [1,2,3].map{|x| x.to_s} > > Have not done any benchmarking "... but by counting under my breath while the code runs, I'm POSITIVE Ruby is much faster that Python!" By complaining about Python being too slow while admitting that you haven't actually tested the speed of your preferred alternative, you have *negative* credibility. > but far more useful from the programmers > POV. And that really stinks because map is such a useful tool it's a > shame to waste it. Here are some test to back up the rant. > > >>>> import time >>>> def test1(): > l = range(10000) > t1 = time.time() > map(lambda x:x+1, l) > t2= time.time() > print t2-t1 That's a crappy test. (1) You include the cost of building a new function each time. (2) You make no attempt to protect against the inevitable variation in speed caused by external processes running on a modern multi-process operating system. (3) You are reinventing the wheel (badly) instead of using the timeit module. >>>> def test2(): > l = range(10000) > t1 = time.time() > for x in l: > x + 1 > t2 = time.time() > print t2-t1 The most obvious difference is that in test1, you build a 10,000 item list, while in test2, you don't. And sure enough, not building a list is faster than building a list: >>>> test1() > 0.00200009346008 >>>> test2() > 0.000999927520752 >>>> def test3(): > l = range(10000) > t1 = time.time() > map(str, l) > t2= time.time() > print t2-t1 > > >>>> def test4(): > l = range(10000) > t1 = time.time() > for x in l: > str(x) > t2= time.time() > print t2-t1 > > >>>> test3() > 0.00300002098083 >>>> test4() > 0.00399994850159 Look ma, not building a list is still faster than building a list! > So can anyone explain this poor excuse for a map function? Maybe GVR > should have taken it out in 3.0? *scratches head* So, let's do some proper tests. Using Python 2.6 on a fairly low-end desktop, and making sure all the alternatives do the same thing: >>> from timeit import Timer >>> t1 = Timer('map(f, L)', 'f = lambda x: x+1; L = range(10000)') >>> t2 = Timer('''accum = [] .... for item in L: .... accum.append(f(item)) .... .... ''', 'f = lambda x: x+1; L = range(10000)') >>> >>> min(t1.repeat(number=1000)) 3.5182700157165527 >>> min(t2.repeat(number=1000)) 6.702117919921875 For the benefit of those who aren't used to timeit, the timings at the end are the best-of-three of repeating the test code 1000 times. The time per call to map is 3.5 milliseconds compared to 6.7 ms for unrolling it into a loop and building the list by hand. map is *much* faster. How does it compare to a list comprehension? The list comp can avoid a function call and do the addition inline, so it will probably be significantly faster: >>> t3 = Timer('[x+1 for x in L]', "L = range(10000)") >>> min(t3.repeat(number=1000)) 2.0786428451538086 And sure enough it is. But when you can't avoid the function call, the advantage shifts back to map: >>> t4 = Timer('map(str, L)', "L = range(10000)") >>> t5 = Timer('[str(x) for x in L]', "L = range(10000)") >>> min(t4.repeat(number=1000)) 3.8360331058502197 >>> min(t5.repeat(number=1000)) 6.6693520545959473 Lessons are: (1) If you're going to deny being a troll, avoid making inflammatory statements unless you can back them up. (2) Understand what you are timing, and don't compare apples to snooker balls just because they're both red. (3) Timing tests are hard to get right. Use timeit. (4) map is plenty fast. Have a nice day. -- Steven
From: D'Arcy J.M. Cain on 6 Jun 2010 19:56 On Mon, 07 Jun 2010 05:59:02 +1000 Lie Ryan <lie.1296(a)gmail.com> wrote: > > foo = lambda x: [y + 1 for y in x] > > [foo(x) for x in [[4, 6, 3], [6, 3, 2], [1, 3, 5]]] > > > > Didn't seem like such a long walk. > > > > that's because you're simplifying the problem, the correct walk is: Well, since it gives the same answer and you didn't actually state the problem I'm not sure how you can make that statement. Show me the unit test that defines the problem. -- D'Arcy J.M. Cain <darcy(a)druid.net> | Democracy is three wolves http://www.druid.net/darcy/ | and a sheep voting on +1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Sniffer Linux with Raw Socket Next: Drop Table w/ MySQLdb? |