views:

257

answers:

9

Sometimes, I just want to execute a function for a list of entries -- eg.:

for x in wowList:
   installWow(x, 'installed by me')

Sometimes I need this stuff for module initialization, so I don't want to have a footprint like x in global namespace. One solution would be to just use map together with lambda:

map(lambda x: installWow(x, 'installed by me'), wowList)

But this of course creates a nice list [None, None, ...] so my question is, if there is a similar function without a return-list -- since I just don't need it.

(off course I can also use _x and thus not leaving visible footprint -- but the map-solution looks so neat ...)

+3  A: 

You might try this:

filter(lambda x: installWow(x, 'installed by me') and False, wowList)

That way, the return result is an empty list no matter what.

Or you could just drop the and False if you can force installWow() to always return False (or 0 or None or another expression that evaluates false).

Mark Rushakoff
This looks good rather good, since an empty list is better as a growing list. But why do I need "or False"?
Juergen
Same thing with list comprehension: [1 for x in wowList if installWow(x, 'installed by me') and False]
stephan
@stephan: very neat!
Juergen
@Juergen: you're right, the or False was unnecessary because (_ and False) is by definition False. Duh on my part :) Updated accordingly.
Mark Rushakoff
@stephan, your LC still pollutes the module's namespace with x (in Python 2.*), so it has zero advantage wrt the plain loop which the OP hates!
Alex Martelli
@stephan: `[]` introduces `x` into global namespace (if it is executed at module level)
J.F. Sebastian
@Alex Martelli, @J.F. Sebastian: Thanks for pointing out that the list comprehension only works as desired for Python 3.x.
stephan
+3  A: 

Every expression evaluates to something, so you always get a result, whichever way you do it. And any such returned object (just like your list) will get thrown away afterwards because there's no reference to it anymore.

To clarify: Very few things in python are statements that don't return anything. Even a function call like

doSomething()

still returns a value, even if it gets discarded right away. There is no such thing as Pascal's function / procedure distinction in python.

balpha
That might be right. But it is just a big difference, if a function (also a builtin function) creates a big, fat list that is just wasted or if the result is just None. Just accumulating values in a list costs temporary memory and CPU cycles.
Juergen
I totally agree; I wasn't saying you don't have a point. But the created overhead probably would be the least if you use your for loop example (you could del the x afterwards if you don't want it lying around).
balpha
Ok, to answer your clarification: I knew that, but map accumulates that something -- None. So the result of map is [None, None, ...] I want to avoid this.
Juergen
I figured you knew that, the clarification was more in the general sense of "we're building an encyclopedia here." Anyway, I don't think we really disagree on anything here :-)
balpha
That's ok. I also think, there is not so big disagreement here. It is just a matter of style here. I am looking for an elegant and fast implementation ... what might be a little heretic to some Python purists ...
Juergen
A: 

You could use a filter and a function that doesn't return a True value. You'd get an empty return list since filter only adds the values which evaluates to true, which I suppose would save you some memory. Something like this:

#!/usr/bin/env python
y = 0
def myfunction(x):
  global y
  y += x

input = (1, 2, 3, 4)

print "Filter output: %s" % repr(filter(myfunction, input))
print "Side effect result: %d" % y

Running it produces this output:

Filter output: ()
Side effect result: 10
Alexander Ljungberg
Don't know, why the others don't liked it. I like it. Off course, the implicit condition that myfunction must not return True or something that evaluates to True can make troubles when you want to use it for general usage. But since the other solutions don't hit my intentions much better, I accept your answer also for the reason the others gave such a negative vote.
Juergen
+11  A: 

How about this?

for x in wowList:
    installWow(x, 'installed by me')
del x
RichieHindle
Ok, another possible solution to the original problem, but does not fit into the intented question.
Juergen
@Juergen: You said "I don't want to have a footprint like x in global namespace". Later you said "I am looking for an elegant and fast implementation". Now this answer may not answer the question in the title ("Is there a map without result in python?") but it certainly does answer the question as a whole. That was a harsh downvote, for a answer that tries to solve your problem in an elegant way.
RichieHindle
@RichieHindle: Yes, I was looking for an "elegant" and "fast" solution. What about "elegant"?? "del x" is possible, but not elegant in my opinion. Ok, I don't wanted to say it -- this solution is so easy, that I also was using it, but it is not elegant in my opinion. And I don't wanted to list all "unelegant" solutions. The questions title was clearly enough stating what direction I was thinking. Sorry for any inconveniance!
Juergen
@Juergen: del x ist way more elegant than using a functional construct like map() or reduce() for the side-effect it produces. If the function application is the important part instead of the returned result then use a loop to make this explicit.
unbeknown
@unbeknown: good point. functional applications used for side-effect are almost as "inelegant" as is possible. +1 to your comment and +1 to the answer for clarity.
TokenMacGuy
+3  A: 

if it is ok to distruct wowList

while wowList: installWow(wowList.pop(), 'installed by me')

if you do want to maintain wowList

wowListR = wowList[:]
while wowListR: installWow(wowListR.pop(), 'installed by me')

and if order matters

wowListR = wowList[:]; wowListR.reverse()
while wowListR: installWow(wowListR.pop(), 'installed by me')

Though as the solution of the puzzle I like the first :)

Anurag Uniyal
If it is ok to destruct the wowList, perhaps prepending a wowList.reverse() would be appropriate, since the order of the list items could be important. pop() pops off the end of the list. pop(0) is inefficient since it continuously shifts all remaining items towards the start of the list.
ΤΖΩΤΖΙΟΥ
+3  A: 

I can not resist myself to post it as separate answer

reduce(lambda x,y: x(y, 'installed by me') , wowList, installWow)

only twist is installWow should return itself e.g.

def installWow(*args):
    print args
    return installWow
Anurag Uniyal
+6  A: 

You could make your own "each" function:


def each(fn, items):
    for item in items:
        fn(item)


# called thus
each(lambda x: installWow(x, 'installed by me'), wowList)

Basically it's just map, but without the results being returned. By using a function you'll ensure that the "item" variable doesn't leak into the current scope.

John Montgomery
+1  A: 

first rewrite the for loop as a generator expression, which does not allocate any memory.

(installWow(x,  'installed by me') for x in wowList )

But this expression doesn't actually do anything without finding some way to consume it. So we can rewrite this to yield something determinate, rather than rely on the possibly None result of installWow.

( [1, installWow(x,  'installed by me')][0] for x in wowList )

which creates a list, but returns only the constant 1. this can be consumed conveniently with reduce

reduce(sum, ( [1, installWow(x,  'installed by me')][0] for x in wowList ))

Which conveniently returns the number of items in wowList that were affected.

TokenMacGuy
+1  A: 

Just make installWow return None or make the last statement be pass like so:


def installWow(item, phrase='installed by me'):
  print phrase
  pass

and use this:


list(x for x in wowList if installWow(x))

x won't be set in the global name space and the list returned is [] a singleton

freegnu