[Tutor] Descriptors and type declaration order

Dave Angel d at davea.name
Thu Jul 14 14:19:42 CEST 2011


On 07/14/2011 05:44 AM, Knacktus wrote:
> Hi guys,
>
> I've got the following (not working) code:
>
> class Attribute(object):
>
>      def __init__(self, attribute_name, att_type_name):
>          self._attribute_name = attribute_name
>          try:
>              self._attribute_type = globals()[att_type_name]
>          except KeyError:
>              self._attribute_type = getattr(globals()["__builtins__"],
> att_type_name)
>
>      def __get__(self, obj, obj_type):
>          return getattr(obj, self._attribute_name)
>
>      def __set__(self, obj, value):
>          if isinstance(value, self._attribute_type):
>              setattr(obj, self._attribute_name, value)
>          else:
>              raise ItemTypeException(self._attribute_type, type(value))
>
> class BaseItem(object):
>
>      ident = Attribute("ident", "int")
>      owner = Attribute("owner", "str")
>      item = Attribute("item", "BaseItem")
>
> if __name__ == "__main__":
>      print "About to create an item"
>      test = BaseItem()
>      print "OK"
>
> The problem is that the descriptors are created when the module is
> evaluated. But at this time the class BaseItem is not known yet. Any ideas?
>
> Cheers,
>
> Jan
>
It's customary to include a traceback when asking a question like this, 
because many people might then be able to give advice without actually 
having to create the file and try it.

So here's the error I get with 2.7.1

Traceback (most recent call last):
   File "test2.py", line 19, in <module>
     class BaseItem(object):
   File "test2.py", line 23, in BaseItem
     item = Attribute("item", "BaseItem")
   File "test2.py", line 8, in __init__
     self._attribute_type = getattr(globals()["__builtins__"], 
att_type_name)
AttributeError: 'module' object has no attribute 'BaseItem'


I had expected from your question that the error would occur when trying 
to instantiate the 'test' instance of BaseItem, but it never gets that 
far. The problem is that in creating the class, you're trying to use the 
class' type.  But that's not added to the globals dictionary till the 
class definition is complete.

One workaround is to move the last line of the class definition outside, 
so you end up with the following:

class BaseItem(object):

     ident = Attribute("ident", "int")
     owner = Attribute("owner", "str")

BaseItem.item = Attribute("item", "BaseItem")

There may very well be a better answer, and I'd enjoy knowing what it is.
-

DaveA



More information about the Tutor mailing list