Gabriel Genellina a écrit :
En Fri, 09 Mar 2007 06:25:08 -0300, Erwan Adam <er********@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@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.