Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

invoke method on many instances

6 views
Skip to first unread message

Alan G Isaac

unread,
Jul 17, 2009, 1:19:50 AM7/17/09
to
As a recurrent situation, I need to invoke the same method
on many instances. Speed matters, but the solution should
be pure Python. Is the following convenience function
a reasonable approach?

def apply2(itr, methodname, *args, **kwargs):
f = operator.methodcaller(methodname, *args, **kwargs)
for item in itr:
f(item)

(Comment: in the case at hand, the methods return None.)

Thank you,
Alan Isaac


Steven D'Aprano

unread,
Jul 17, 2009, 3:45:08 AM7/17/09
to
On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:

> As a recurrent situation, I need to invoke the same method on many
> instances. Speed matters, but the solution should be pure Python. Is
> the following convenience function a reasonable approach?
>
> def apply2(itr, methodname, *args, **kwargs):
> f = operator.methodcaller(methodname, *args, **kwargs)
> for item in itr:
> f(item)

I don't particularly like your naming conventions, but never mind.

You could also try this:

for obj in objects:
getattr(obj, methodname)(*args, **kwargs)


See also these recipes from the "Python Cookbook":

http://code.activestate.com/recipes/52289/
http://code.activestate.com/recipes/87370/


--
Steven

Alan G Isaac

unread,
Jul 18, 2009, 11:31:46 AM7/18/09
to
> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:
>> def apply2(itr, methodname, *args, **kwargs):
>> f = operator.methodcaller(methodname, *args, **kwargs)
>> for item in itr:
>> f(item)


On 7/17/2009 3:45 AM Steven D'Aprano apparently wrote:
> for obj in objects:
> getattr(obj, methodname)(*args, **kwargs)


Are there any obvious considerations in choosing
between those two?

> See also these recipes from the "Python Cookbook":
> http://code.activestate.com/recipes/52289/
> http://code.activestate.com/recipes/87370/

Interesting.

Thanks,
Alan

Terry Reedy

unread,
Jul 18, 2009, 6:30:08 PM7/18/09
to pytho...@python.org
Alan G Isaac wrote:
>> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:
>>> def apply2(itr, methodname, *args, **kwargs):
>>> f = operator.methodcaller(methodname, *args, **kwargs)
>>> for item in itr:
>>> f(item)
>
>
> On 7/17/2009 3:45 AM Steven D'Aprano apparently wrote:
>> for obj in objects:
>> getattr(obj, methodname)(*args, **kwargs)
>
>
> Are there any obvious considerations in choosing
> between those two?

I would use the straightforward getattr idiom.

Rainer Grimm

unread,
Jul 19, 2009, 7:08:00 AM7/19/09
to
Hallo Alan,

> def apply2(itr, methodname, *args, **kwargs):
>     f = operator.methodcaller(methodname, *args, **kwargs)
>     for item in itr:
>         f(item)
you can do it in a functional way.

>>> class A(object):
... def hello(self): return "hello: " + str
( self.__class__.__name__ )
...
>>> class B(A):pass
...
>>> class C(A):pass
...
>>> a=A()
>>> b=B()
>>> c=C()
>>> a.hello()
'hello: A'
>>> b.hello()
'hello: B'
>>> c.hello()
'hello: C'
>>>
>>> map( (lambda obj : getattr(obj,"hello")()),(a,b,c))
['hello: A', 'hello: B', 'hello: C']
>>> [ getattr(obj,"hello")() for obj in (a,b,c)]
['hello: A', 'hello: B', 'hello: C']

Greetings from Rottenburg,
Rainer

Piet van Oostrum

unread,
Jul 19, 2009, 9:24:26 AM7/19/09
to
>>>>> Rainer Grimm <r.g...@science-computing.de> (RG) a �crit:

>RG> Hallo Alan,


>>> def apply2(itr, methodname, *args, **kwargs):
>>> � � f = operator.methodcaller(methodname, *args, **kwargs)
>>> � � for item in itr:
>>> � � � � f(item)

>RG> you can do it in a functional way.

>>>>> class A(object):
>RG> ... def hello(self): return "hello: " + str
>RG> ( self.__class__.__name__ )
>RG> ...
>>>>> class B(A):pass
>RG> ...
>>>>> class C(A):pass
>RG> ...
>>>>> a=A()
>>>>> b=B()
>>>>> c=C()
>>>>> a.hello()
>RG> 'hello: A'
>>>>> b.hello()
>RG> 'hello: B'
>>>>> c.hello()
>RG> 'hello: C'


>>>>>
>>>>> map( (lambda obj : getattr(obj,"hello")()),(a,b,c))

>RG> ['hello: A', 'hello: B', 'hello: C']


>>>>> [ getattr(obj,"hello")() for obj in (a,b,c)]

>RG> ['hello: A', 'hello: B', 'hello: C']

But that creates an unnecessary list.
--
Piet van Oostrum <pi...@cs.uu.nl>
URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
Private email: pi...@vanoostrum.org

Gabriel Genellina

unread,
Jul 20, 2009, 3:29:17 AM7/20/09
to pytho...@python.org
En Sat, 18 Jul 2009 12:31:46 -0300, Alan G Isaac <alan....@gmail.com>
escribi�:

>> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:
>>> def apply2(itr, methodname, *args, **kwargs):
>>> f = operator.methodcaller(methodname, *args, **kwargs)
>>> for item in itr:
>>> f(item)
>
>
> On 7/17/2009 3:45 AM Steven D'Aprano apparently wrote:
>> for obj in objects:
>> getattr(obj, methodname)(*args, **kwargs)
>
>
> Are there any obvious considerations in choosing
> between those two?

The operator.methodcaller version is faster in my tests for large
collections, but slightly slower when you have very few elements.

<code>
import operator
import timeit

class X:
def method(self, x, y, **kw): pass

def apply1(itr, methodname, *args, **kwargs):
for item in itr:
getattr(item, methodname)(*args, **kwargs)

def apply2(itr, methodname, *args, **kwargs):
f = operator.methodcaller(methodname, *args, **kwargs)
for item in itr:
f(item)

L=[X() for _ in range(3000)]
apply1(L,'method', 1, 2, foo=3)
apply2(L,'method', 1, 2, foo=3)

timeit.timeit(setup="from __main__ import apply1,apply2,L",
stmt="apply1(L,'method', 1, 2, foo=3)", number=1000)
timeit.timeit(setup="from __main__ import apply1,apply2,L",
stmt="apply2(L,'method', 1, 2, foo=3)", number=1000)
</code>

--
Gabriel Genellina

Simon Forman

unread,
Jul 21, 2009, 10:30:56 AM7/21/09
to
On Jul 20, 3:29 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Sat, 18 Jul 2009 12:31:46 -0300, Alan G Isaac <alan.is...@gmail.com>  
> escribió:

If your instances are all of the same class you can pass in the method
directly like so:

def apply3(iterator, method, *args, **kwargs):
for item in iterator:
method(item, *args, **kwargs)

class X:
def method(self, x, y, **kw): pass

items = [X() for _ in range(10)]

apply3(items, X.method, 1, 2, foo=3)

HTH,
~Simon

Alan G Isaac

unread,
Jul 22, 2009, 9:14:12 AM7/22/09
to
>>> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:
>>>> def apply2(itr, methodname, *args, **kwargs):
>>>> f = operator.methodcaller(methodname, *args, **kwargs)
>>>> for item in itr:
>>>> f(item)


>> On 7/17/2009 3:45 AM Steven D'Aprano apparently wrote:
>>> for obj in objects:
>>> getattr(obj, methodname)(*args, **kwargs)


> En Sat, 18 Jul 2009 12:31:46 -0300, Alan G Isaac:


>> Are there any obvious considerations in choosing
>> between those two?


On 7/20/2009 3:29 AM Gabriel Genellina apparently wrote:
> The operator.methodcaller version is faster in my tests for large
> collections, but slightly slower when you have very few elements.


So it seems. Is this easily explained?

Thanks,
Alan Isaac

Gabriel Genellina

unread,
Jul 22, 2009, 8:10:54 PM7/22/09
to pytho...@python.org
En Wed, 22 Jul 2009 10:14:12 -0300, Alan G Isaac <alan....@gmail.com>
escribi�:

>>>> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:

NLMPI

--
Gabriel Genellina

Aahz

unread,
Jul 23, 2009, 8:27:35 PM7/23/09
to
In article <mailman.3561.1248307...@python.org>,
Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>
>NLMPI

What?
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. :-)"
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22

Gabriel Genellina

unread,
Jul 24, 2009, 6:06:29 AM7/24/09
to pytho...@python.org
En Thu, 23 Jul 2009 21:27:35 -0300, Aahz <aa...@pythoncraft.com> escribi�:

> In article <mailman.3561.1248307...@python.org>,
> Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>>
>> NLMPI
>
> What?

IHNFI

--
Gabriel Genellina

Aahz

unread,
Jul 26, 2009, 11:44:02 AM7/26/09
to
In article <mailman.3648.1248429...@python.org>,

Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>En Thu, 23 Jul 2009 21:27:35 -0300, Aahz <aa...@pythoncraft.com> escribi�:
>> In article <mailman.3561.1248307...@python.org>,
>> Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>>>
>>> NLMPI
>>
>> What?
>
>IHNFI

What? Abbreviations are fine, but if someone asks you about one, it
would be nice to just expand it instead of replying with another
abbreviation.

Gabriel Genellina

unread,
Jul 26, 2009, 5:06:48 PM7/26/09
to pytho...@python.org
En Sun, 26 Jul 2009 12:44:02 -0300, Aahz <aa...@pythoncraft.com> escribiᅵ:

> In article <mailman.3648.1248429...@python.org>,
> Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>> En Thu, 23 Jul 2009 21:27:35 -0300, Aahz <aa...@pythoncraft.com>
>> escribiᅵ:

>>> In article <mailman.3561.1248307...@python.org>,
>>> Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>>>>
>>>> NLMPI
>>>
>>> What?
>>
>> IHNFI
>
> What? Abbreviations are fine, but if someone asks you about one, it
> would be nice to just expand it instead of replying with another
> abbreviation.

Ok, if you insist...

NLMPI = Ni La Mᅵs Puta Idea.
IHNFI = I Have No Fucking Idea.

--
Gabriel Genellina

Aahz

unread,
Jul 26, 2009, 10:44:24 PM7/26/09
to
In article <mailman.3747.1248642...@python.org>,

Gabriel Genellina <gags...@yahoo.com.ar> wrote:
>
>Ok, if you insist...
>
>NLMPI = Ni La M�s Puta Idea.

>IHNFI = I Have No Fucking Idea.

Thanks!

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer

0 new messages