invoke method on many instances
Simon Forman
sajmikins at gmail.com
Tue Jul 21 10:30:56 EDT 2009
On Jul 20, 3:29 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
wrote:
> En Sat, 18 Jul 2009 12:31:46 -0300, Alan G Isaac <alan.is... at 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
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
More information about the Python-list
mailing list