Recursion with __setattr__

Chris Young 212357 at students.smjuhsd.k12.ca.us
Sun Oct 16 03:55:28 EDT 2005


Operating Ubunutu Linux 5.04 on iMac 333mhz
Python 2.4.1 in IDLE 1.1.1

In trying to create a interactive drawing framework in Python I came across
the idea of binding attributes of one object to attributes of another.

The way it works is when obj1.attr1 is set obj2.attr2 should have it's
__setattr__ method called as well. But it ends up giving me a recursion error.

The attribute synchronization is shown below:

#file: sync.py

def sync(attr1,obj1,obj2,attr2=None):
   """Synchronize attribute access

   attr1:
   name of attribute to synchronize
   attr2:
   (optional) attribute name to use when setting second object.
"""
       if not attr2: attr2 = attr1
       # rename old __setattr__'s
       try:
           obj1.__old_setattr__ = obj1.__setattr__
           obj2.__old_setattr__ = obj2.__setattr__
       except AttributeError: pass
       # modify mirrored attributes on attribute change
       def hook_setattr(inst):
       # Hey! Only classes have special methods!
           class sethook(inst.__class__):
               def __setattr__(self,name,value):
                       try:
                           self.__old_setattr__(name,value)
                       except AttributeError: pass
                       if name in self.__syncdict__:
                           entry = self.__syncdict__[name]
                           for mirror,attr in entry: pass
# recursion error here:       setattr(mirror,attr,value)
           #sethook.__name__ = inst.__class__.__name__ # magic?
           inst.__class__ = sethook
       # append synchronization info
   try:
       obj1.__syncdict__[attr1].append(obj2,attr2)
   except AttributeError:
       obj1.__syncdict__ = {attr1: [(obj2,attr2)]}
   try:
       obj2.__syncdict__[attr2].append(obj1,attr1)
   except AttributeError:
       obj2.__syncdict__ = {attr2: [(obj1,attr1)]}
       # make the magic work
       hook_setattr(obj1)
       hook_setattr(obj2)

When I try to call this like sync('attr',obj,obj2) I get a recursion error.
I could understand this happening if I was calling setattr on itself, but
why the other object?

Any help is greatly appreciated. Also, any pointers on efficiency or easier
ways is also welcome. Thanks in
advance.




More information about the Python-list mailing list