Re: Pb with descriptor and super ...

2007-03-09 Thread Arnaud Delobelle
On Mar 9, 11:22 am, Erwan Adam <[EMAIL PROTECTED]> wrote:
[snip]
>
> [EMAIL PROTECTED] /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 
> 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 

It seems to me that it is the built-in super which has the correct
behaviour.  When you write obj.attr, python calls  attr.__get__(obj,
type(obj)) and not attr.__get__(obj) which sets the second arg to
None. You can check this by creating a barebone descriptor that simply
prints its arguments:

class D(object):
def __get__(self, obj, objtype):
print obj, objtype

class A(object):
d=D()

A().d
<__main__.A object at 0x133c5f0>  # objtype is not
None!

Therefore in your case when you do super(B, b).attr then
A.__dict__['attr'].__get__(b, type(b)) is called. You can try this, it
should give the same output as builtin super.

> 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 

Neither of these are right I think. If my explanation above is right
the correct line should be:
x = x.__get__(self.__obj__, type(self.__obj__))

HTH

--
Arnaud

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Pb with descriptor and super ...

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 08:22:46 -0300, Erwan Adam <[EMAIL PROTECTED]>  
escribió:

> 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 :

It appears that there is some disagreement on how the super object should  
behave.
If you want to know what it actually *does* now (not what it *should* do)  
you can look at typeobject.c, but it's a bit hard to read, and I don't  
understand it in full...
Maybe looking at the test suite is easier, in test_descr.py

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Pb with descriptor and super ...

2007-03-09 Thread Erwan Adam
Gabriel Genellina a écrit :
> En Fri, 09 Mar 2007 06:25:08 -0300, Erwan Adam <[EMAIL PROTECTED]> 
> 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 :

[EMAIL PROTECTED] /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 
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 

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.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Pb with descriptor and super ...

2007-03-09 Thread Erwan Adam
Erwan Adam a écrit :
> Hi all,
> 
> I have a problem with the use of descriptors
> and super. The file is :
> 
> # ---
> 
> class Desc(object):
> def __init__(self, class_name):
> self.class_name = class_name
> return
> def __get__(self, obj, typ):
> 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 "---"
> print "Getting b.attr ..."
> print "I hope that  : class_name is B, obj is b and typ is B"
> b.attr
> print "---"
> print "Getting super(B, b).attr ..."
> print "I hope that  : class_name is A, obj is b and typ is A but it is 
> not the case !"
> super(B, b).attr
> print "---"
> 
> # ---
> 
> and the result is :
> 
> ---
> Getting b.attr ...
> I hope that  : class_name is B, obj is b and typ is B
> Desc.__get__ : class_name is B, obj is <__main__.B object at 0xb7b1f8ec> 
> and typ is 
> ---
> Getting super(B, b).attr ...
> I hope that  : class_name is A, obj is b and typ is A but it is not the 
> case !
> Desc.__get__ : class_name is A, obj is <__main__.B object at 0xb7b1f8ec> 
> and typ is 
> ---
> 
> I expected that when getting super(B, b).attr, typ is A, but it is not
> the case ...

Moreover, on the page :

http://users.rcn.com/python/download/Descriptor.htm

the author writes :

"The call super(B, obj).m() searches obj.__class__.__mro__ for the base 
class A immediately following B and then returns 
A.__dict__['m'].__get__(obj, A)."

which it seems not the case ...

Is it a bug or a mis-understood ?

Regards,

  E.A.


> 
> python used :
> 
> [EMAIL PROTECTED] /home/adam/Work/Python]> python
> Python 2.4.3 (#2, Sep 18 2006, 21:07:35)
> [GCC 4.1.1 20060724 (prerelease) (4.1.1-3mdk)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>  >>>
> 
> 
> Best regards,
> 
> 
>   E.A.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Pb with descriptor and super ...

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 06:25:08 -0300, Erwan Adam <[EMAIL PROTECTED]>  
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

-- 
http://mail.python.org/mailman/listinfo/python-list