"optimizing out" getattr

D

Daishi Harada

Hi,

I'd like to get the 'get2' function below to
perform like the 'get1' function (I've included
timeit.py results).

I'm not sure how to write 'mkget' to do achieve
this, however, except to use 'exec' - is that what
would be necessary?

Thanks in advance,
d

---
class A:
a = 1
b = 2
a = A()
labels = ('a', 'b')
def get1(x):
return (x.a, x.b)
def mkget(attrs):
def getter(x):
return tuple(getattr(x, label) for label in attrs)
return getter
get2 = mkget(labels)

# % timeit.py -s "import test" "test.get1(test.a)"
# 1000000 loops, best of 3: 0.966 usec per loop
# % timeit.py -s "import test" "test.get2(test.a)"
# 100000 loops, best of 3: 4.46 usec per loop
---
 
S

Stephen Thorne

Hi,

I'd like to get the 'get2' function below to
perform like the 'get1' function (I've included
timeit.py results).

Do you have profiling results that show that a significant percentage
of your programs time is being spent inside this function?

If you don't, then you're wasting your time doing unnecessery optimisation.
 
P

Peter Otten

Daishi said:
I'd like to get the 'get2' function below to
perform like the 'get1' function (I've included
timeit.py results).
labels = ('a', 'b')
def get1(x):
return (x.a, x.b)
def mkget(attrs):
def getter(x):
return tuple(getattr(x, label) for label in attrs)
return getter
get2 = mkget(labels)

# % timeit.py -s "import test" "test.get1(test.a)"
# 1000000 loops, best of 3: 0.966 usec per loop
# % timeit.py -s "import test" "test.get2(test.a)"
# 100000 loops, best of 3: 4.46 usec per loop
I'm not sure how to write 'mkget' to do achieve
this, however, except to use 'exec' - is that what
would be necessary?

No, you can just sit back and wait -- for Python 2.5:

$ cat attr_tuple25.py
import operator

class A:
a = 1
b = 2

get2 = operator.attrgetter("a", "b")

def get1(x):
return x.a, x.b

$ python2.5 -m timeit -s'from attr_tuple25 import A, get1, get2' 'get1(A)'
1000000 loops, best of 3: 0.813 usec per loop
$ python2.5 -m timeit -s'from attr_tuple25 import A, get1, get2' 'get2(A)'
1000000 loops, best of 3: 0.495 usec per loop

Time till release is not included in the timings :)

Peter
 
K

Kent Johnson

Peter said:
Daishi Harada wrote:



No, you can just sit back and wait -- for Python 2.5:

$ cat attr_tuple25.py
import operator

class A:
a = 1
b = 2

get2 = operator.attrgetter("a", "b")

def get1(x):
return x.a, x.b

$ python2.5 -m timeit -s'from attr_tuple25 import A, get1, get2' 'get1(A)'
1000000 loops, best of 3: 0.813 usec per loop
$ python2.5 -m timeit -s'from attr_tuple25 import A, get1, get2' 'get2(A)'
1000000 loops, best of 3: 0.495 usec per loop

With Python 2.4 you can at least get closer to the hardcoded version:

F:\>type attr_tuple.py
import operator

class A:
a = 1
b = 2

getA = operator.attrgetter("a")
getB = operator.attrgetter("b")

def get2(x):
return getA(x), getB(x)

def get1(x):
return x.a, x.b

F:\>python -m timeit -s"from attr_tuple import A, get1, get2" "get1(A)"
1000000 loops, best of 3: 0.658 usec per loop

F:\>python -m timeit -s"from attr_tuple import A, get1, get2" "get2(A)"
1000000 loops, best of 3: 1.04 usec per loop

Kent
 
D

Daishi Harada

Peter said:
No, you can just sit back and wait -- for Python 2.5:

Thanks for the tip;
Although for my current use
I can't target 2.5, I hadn't even
noticed the attr/itemgetter
additions to operator in 2.4,
so I appreciate the pointer
for future reference.
d
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top