to setattr or def setProp()

Bruno Desthuilliers onurb at xiludom.gro
Tue Nov 14 11:12:01 CET 2006

jm.suresh at wrote:
> I have a class for rectangle and it has two points in its __slots__ .
> However, we can derive a number of properties like width, height,
> centerPoint etc from these two points. Now, I want to be able to set
> and get these properties directly from the instances. I can either def
> __setattr__ , __getattr__ 

But this won't help with introspection...

> or I can define function for each property
> like setWidth(), setHeight() . Which one would be faster?

You mean faster performances or faster to implement ?

> I would
> prefer doing through __setattr__, __getattr__ because it makes the code
> more readable.

You mean the client code ?

> However, speed is a concern I would have to do these operations in few
> thousand iterations for about 50-100 rectangles.

The canonical solution is to use either properties or custom
descriptors[1]. Custom descriptors should be a bit faster than
properties (since you save a couple function calls), but I have not done
any benchmark... It should also be a bit faster than __getattr__, which
is only used as a fallback when all other lookup rules have failed (here
again, don't take me on words and do some benchmarking). As a last
point, descriptors show up as class and instance attributes, which helps
with introspection.

class Height(object):
  def __get__(self, instance, cls):
    if instance is None: return self
    return instance.bottomright.y - instance.topleft.y

 def __set__(self, instance, value):
    instance.bottomright.y = instance.topleft.y + value

class Width(object):
  def __get__(self, instance, cls):
    if instance is None: return self
    return instance.bottomright.x - instance.topleft.x

 def __set__(self, instance, value):
    instance.bottomright.x = instance.topleft.x + value

class Rectangle(object):
   def __init__(self):
     self.topleft = Point(10, 10)
     self.bottomright = Point(20, 30)

   height = Height()
   width = Width()

r = Rectangle()
r.with = 40

(not tested)

[1] :

My 2 cents...
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"

More information about the Python-list mailing list