0

Is there a way to attach a function (same function) to all the elements of an array without looping through and attaching it one by one?

So like

# create function foo from some computation
foo # some def    

# list
objects # list of objects

# attach same foo function to all elements of objects
# maybe using a decorator?

# loop through list to execute foo
for obj in objects:
    obj.foo()

Let me explain this more:

Of course I can just assign the value of an object like

obj.attr = value

or for an object list:

for obj in objects:
    obj.attr = value

What I am trying to avoid is setting the value of an attr on each single object, but rather applying a function on the entire list/array and each element would execute that function.

Derek
  • 11,980
  • 26
  • 103
  • 162
  • "All elements" is highly dubious, considering that Python's "array" structure is a list, and can expand to be as large as you need to be. Do you want to overwrite the location with the function, or do you want to apply the function to each argument in the list? – Makoto Jun 03 '13 at 01:42
  • possible duplicate of [Adding a Method to an Existing Object](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object) – GWW Jun 03 '13 at 01:42
  • @GWW that is not the question I am trying to ask, please read the question more carefully – Derek Jun 03 '13 at 02:02
  • I apologize your explanation was confusing. – GWW Jun 03 '13 at 02:19

3 Answers3

4

You could make a function to wrap it up:

def for_each(l, f):
    for item in l:
        f(item)

Then for a function foo you could do this:

for_each(objects, foo)

For a method foo you could do this:

for_each(objects, lambda item: item.foo())

Or this:

from operator import methodcaller
for_each(objects, methodcaller('foo'))

In Python 2, you can also use map:

map(foo, objects)

For Python 3, you'll have to wrap that in list(...). In either version, you can use list comprehensions:

[foo(item) for item in objects]

However, if you're calling the function just for its side effect rather than transforming the list somehow, I'd recommend against these last two ways as it's against the Zen of Python:

Explicit is better than implicit.

And frankly, one more line for a for loop isn't that much.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • don't think this answers my question, I'm trying to avoid looping through the array to set a value to its elements – Derek Jun 03 '13 at 02:05
  • @Derek: I'm afraid I don't understand your question, then. Even with your edit, I'm confused. Can you provide a more concrete example? – icktoofay Jun 03 '13 at 05:10
1

You can use map. It is generally used to create a second list, and will return that value, but you can just ignore it.

map(lambda x: x.foo(), objects)
Kevin
  • 53,822
  • 15
  • 101
  • 132
  • map is essentially doing a for loop through the list and setting values, right? – Derek Jun 03 '13 at 01:57
  • It loops through the list and creates a new list with the returned values, yes. It doesn't alter the list it's called on. – Kevin Jun 03 '13 at 02:05
  • my question was probably confusing, but I'm trying to avoid looping through the array to set a value to its elements – Derek Jun 03 '13 at 02:06
  • You're going to have to loop through the array somehow, either implicitly (like this, where the map function hides the loop) or explicitly (a for loop). There's no magic function that just does something to every element of a list without looping through it, it fundamentally can't exist. – Kevin Jun 03 '13 at 04:33
0

use numpy vectorize! It will work perfectly for you!

from numpy import np
def fun(x):
    #do something
array = np.array(your_list)
vectfun = np.vectorize(fun)
answer = vectfun(array)

So now answer will be a resulting array consisting of all the items in the previous list with the function applied to them!! Here is an example:

>>> your_list = [1,2,3,4,5]
>>> def fun(x):
...     return x**x
... 
>>> array = np.array((your_list))
>>> vectfun = np.vectorize(fun)
>>> answer = vectfun(array)
>>> answer
array([   1,    4,   27,  256, 3125])
Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128