Performance penalty for using properties?
Peter Otten
__peter__ at web.de
Sun Mar 14 03:27:00 EST 2004
Robert Brewer wrote:
> Peter Otten wrote:
>> Kenneth McDonald wrote:
>>
>> > Now that I'm back to Python and all the new (to me) cool features,
>> > I find I'm using properties a lot, i.e. I'm defining:
>> >
>> > foo = property(fset=..., fget=...)
>> >
>> > for a number of properties, in many of my classes. I'm not using
>> > them for anything performance critical yet, but could see myself
>> > doing so in the future. Can anyone comment on the performance
>> > costs associated with properties vs. simple attribute lookup?
>>
>> It seems I'm becoming obsessed with timeit.py :-)
>
> ISTR Alex Martelli went through such a phase.. ;)
>
>> <property.py>
>> class Test(object):
>> def getvalue(self):
>> return self._value
>> value = property(getvalue)
>>
>> t = Test()
>> t._value = 123
>> </property.py>
>>
>> $ timeit.py -s"from property import t" "t._value"
>> 1000000 loops, best of 3: 0.207 usec per loop
>> $ timeit.py -s"from property import t" "t.getvalue()"
>> 1000000 loops, best of 3: 0.918 usec per loop
>> $ timeit.py -s"from property import t" "t.value"
>> 1000000 loops, best of 3: 1.03 usec per loop
>>
>> Roughly factor five, most of the time being consumed by the
>> implied function call.
>
> I've always used "property" as sugar for when I would otherwise have
> overriden __getattr(ibute)__, in which case the performance is not that
> different.
I can think of other patterns (all untested code). Let's pretend area
calculation were time-costly. Then
class Square:
def __init__(self, x, y):
self.x = x
self.y = y
self.area = x*y
setExtent = __init__
should be less efficient than
class LazySquare(object):
# probably bad, don't do it
def __init__(self, x, y):
self.x = x
self.y = y
def getarea(self):
try:
return self._area
except Attribute:
self._area = self.x * self.y
return self._area
area = property(getarea)
def setExtent(self, x, y):
self.x = x
self.y = y
try:
del self._area
except AttributeError:
pass
most of the time. At present all your gains may be lost by the repeated
overhead of the getarea() calls. Another one:
class A(object):
# probably bad, don't do it
def getValue(self):
return self._value
def setValue(self, newValue):
if complicatedValidityCheck(newValue):
self._value = newValue
else:
raise ValueError
value = property(getValue, setValue)
Here bothering client code with explicit setter calls would give significant
speed gains if write access is rare compared with reading.
I think finding a way for properties to access attributes without wrapping
them into a function call would be worth the effort. The penalty for clean
interfaces should be as low as possible.
Peter
More information about the Python-list
mailing list