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
> 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
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
I would use the straightforward getattr idiom.
>>> 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
>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
>> 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
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
>> 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
>>>> On Fri, 17 Jul 2009 05:19:50 +0000, Alan G Isaac wrote:
NLMPI
--
Gabriel Genellina
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
IHNFI
--
Gabriel Genellina
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
Thanks!
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/
"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