Pb with descriptor and super ...

Erwan Adam erwan.adam at cea.fr
Fri Mar 9 12:22:46 CET 2007


Gabriel Genellina a écrit :
> En Fri, 09 Mar 2007 06:25:08 -0300, Erwan Adam <erwan.adam at cea.fr> 
> escribió:
> 
>> I have a problem with the use of descriptors
>> and super. The file is :
> 
> Descriptors for "super" behave a bit different than for classes. See
> http://www.python.org/2.2/descrintro.html#cooperation
> 
> --Gabriel Genellina
> 

Hi Gabriel,

Thanks for your answer ... I followed the link
and tried to use the "fully functional implementation of
the super() built-in class in pure Python" given
on this page and the result is quite surprising :

# -------------

class Super(object):
     def __init__(self, type, obj=None):
         self.__type__ = type
         self.__obj__ = obj
     def __get__(self, obj, type=None):
         if self.__obj__ is None and obj is not None:
             return Super(self.__type__, obj)
         else:
             return self
     def __getattr__(self, attr):
         if isinstance(self.__obj__, self.__type__):
             starttype = self.__obj__.__class__
         else:
             starttype = self.__obj__
         mro = iter(starttype.__mro__)
         for cls in mro:
             if cls is self.__type__:
                 break
         # Note: mro is an iterator, so the second loop
         # picks up where the first one left off!
         for cls in mro:
             if attr in cls.__dict__:
                 x = cls.__dict__[attr]
                 if hasattr(x, "__get__"):
                     x = x.__get__(self.__obj__)
                 return x
         raise AttributeError, attr

class Desc(object):
     def __init__(self, class_name):
         self.class_name = class_name
         return
     def __get__(self, obj, typ=None):
         print "Desc.__get__ : class_name is %s, obj is %s and typ is 
%s"%(self.class_name, obj, typ)
         return
     pass

class A(object):
     attr = Desc("A")
     pass

class B(A):
     attr = Desc("B")
     pass

b = B()

print "Using built-in super"
attr = super(B, b).attr
print "Using python Super"
attr = Super(B, b).attr

class MySuper(object):
     def __init__(self, type, obj=None):
         self.__type__ = type
         self.__obj__ = obj
     def __get__(self, obj, type=None):
         if self.__obj__ is None and obj is not None:
             return Super(self.__type__, obj)
         else:
             return self
     def __getattr__(self, attr):
         if isinstance(self.__obj__, self.__type__):
             starttype = self.__obj__.__class__
         else:
             starttype = self.__obj__
         mro = iter(starttype.__mro__)
         for cls in mro:
             if cls is self.__type__:
                 break
         # Note: mro is an iterator, so the second loop
         # picks up where the first one left off!
         for cls in mro:
             if attr in cls.__dict__:
                 x = cls.__dict__[attr]
                 if hasattr(x, "__get__"):
                     x = x.__get__(self.__obj__, cls)
                 return x
         raise AttributeError, attr

print "Using python MySuper"
attr = MySuper(B, b).attr


# ------------------------------

it gives :

[adam at is111902 /home/adam/Work/Python]> python super_from_guido.py
Using built-in super
Desc.__get__ : class_name is A, obj is <__main__.B object at 0xb7bc302c> 
and typ is <class '__main__.B'>
Using python Super
Desc.__get__ : class_name is A, obj is <__main__.B object at 0xb7bc302c> 
and typ is None
Using python MySuper
Desc.__get__ : class_name is A, obj is <__main__.B object at 0xb7bc302c> 
and typ is <class '__main__.A'>

the Super gives None for typ ... which is quite surprising !
In MySuper, I just change

                     x = x.__get__(self.__obj__)

by

                     x = x.__get__(self.__obj__, cls)

at the -3 :) line of the class ... and it gives the result I expected
at the beginning : obj is b and typ is A !!!!


Best regards,

                  E.A.



More information about the Python-list mailing list