Re: [Tutor] Calling super classs __init__?

2008-03-23 Thread Andreas Kostyrka

Am Mittwoch, den 19.03.2008, 10:36 -0300 schrieb Ricardo Aráoz:
> Luciano Ramalho wrote:
> > Nowadays the best practice for invoking a method from all superclasses
> > (yes, multiple inheritance) is this:
> > 
> > class SubClass(BaseClass):
> > def __init__(self, t, *args, **kw):
> > super(SubClass, self).__init__(*args, **kw)
> > # do something with t
> > 
> > That way you let Python decide which superclasses your SubClass has,
> > instead of hard-coding it in several places.
> > 
> 
> You are actually hard-coding it here too, "class SubClass(BaseClass):" 
> has "BaseClass" hard-coded. All you do here is hard-code it once instead 
> of twice.

Yes and no. Yes a human has specified the relationships. But you do not
have to specify what other baseclasses your class has. This is relevant
for multiple inheritence, like:

D => B => A
D => C => A

The problem is mostly hiding implementation details.

Using super, you just let Python pick the "next" class to give control.
Using B.__init__ and C.__init__, A.__init__ would be called twice.

Andreas

> 
> > Cheers,
> > 
> > Luciano
> > 
> > 
> > On Tue, Mar 18, 2008 at 9:37 PM, John Fouhy <[EMAIL PROTECTED]> wrote:
> >> On 19/03/2008, Allen Fowler <[EMAIL PROTECTED]> wrote:
> >>  >  I have a super class that accepts many arguments to it's constructor, 
> >> and a subclass that should define one additional argument.
> >>  >
> >>  >  What's the most "pythonic" way to make this work?
> >>
> >>  class BaseClass(object):
> >>   def __init__(self, x, y, z, foo='foo'): # whatever
> >>  # etc
> >>
> >>  class SubClass(BaseClass):
> >>   def __init__(self, t, *args, **kw):
> >> BaseClass.__init__(self, *args, **kw)
> >> # do something with t
> >>
> >>  This does mean that the special sub class argument has to come before
> >>  the base class arguments when you create instances.
> >>
> >>  Whether you call BaseClass.__init__ early or late in the subclass init
> >>  method could depend on what your classes are doing.  Remember, in
> >>  Python, __init__ only initializes objects, it doesn't create them.
> >>  It's just another bit of code that you can call whenever you want.
> >>
> >>  --
> >>  John.
> >>
> >>
> >> ___
> >>  Tutor maillist  -  Tutor@python.org
> >>  http://mail.python.org/mailman/listinfo/tutor
> >>
> > ___
> > Tutor maillist  -  Tutor@python.org
> > http://mail.python.org/mailman/listinfo/tutor
> > 
> 
> 
> ___
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-23 Thread Ricardo Aráoz
Luciano Ramalho wrote:
> Nowadays the best practice for invoking a method from all superclasses
> (yes, multiple inheritance) is this:
> 
> class SubClass(BaseClass):
> def __init__(self, t, *args, **kw):
> super(SubClass, self).__init__(*args, **kw)
> # do something with t
> 
> That way you let Python decide which superclasses your SubClass has,
> instead of hard-coding it in several places.
> 

You are actually hard-coding it here too, "class SubClass(BaseClass):" 
has "BaseClass" hard-coded. All you do here is hard-code it once instead 
of twice.

> Cheers,
> 
> Luciano
> 
> 
> On Tue, Mar 18, 2008 at 9:37 PM, John Fouhy <[EMAIL PROTECTED]> wrote:
>> On 19/03/2008, Allen Fowler <[EMAIL PROTECTED]> wrote:
>>  >  I have a super class that accepts many arguments to it's constructor, 
>> and a subclass that should define one additional argument.
>>  >
>>  >  What's the most "pythonic" way to make this work?
>>
>>  class BaseClass(object):
>>   def __init__(self, x, y, z, foo='foo'): # whatever
>>  # etc
>>
>>  class SubClass(BaseClass):
>>   def __init__(self, t, *args, **kw):
>> BaseClass.__init__(self, *args, **kw)
>> # do something with t
>>
>>  This does mean that the special sub class argument has to come before
>>  the base class arguments when you create instances.
>>
>>  Whether you call BaseClass.__init__ early or late in the subclass init
>>  method could depend on what your classes are doing.  Remember, in
>>  Python, __init__ only initializes objects, it doesn't create them.
>>  It's just another bit of code that you can call whenever you want.
>>
>>  --
>>  John.
>>
>>
>> ___
>>  Tutor maillist  -  Tutor@python.org
>>  http://mail.python.org/mailman/listinfo/tutor
>>
> ___
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
> 


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-21 Thread tiger12506
So super(A, c) refers to the baseclass object?

I don't like this. It partially suggests that A is a superclass of B.
I guess I have to be sure to notice the second parameter which tells of 
which instance I'm finding the superclass.

fyi I totally didn't notice the first parameter of super... was it there in 
previous versions of python?


- Original Message - 
From: "Andreas Kostyrka" <[EMAIL PROTECTED]>
To: "tiger12506" <[EMAIL PROTECTED]>
Cc: 
Sent: Friday, March 21, 2008 4:25 AM
Subject: Re: [Tutor] Calling super classs __init__?

class A(object):
v=lambda self: "A"
class B(object):
v=lambda self: "B"
class C(B,A):
v=lambda self: "C"

print C.__mro__

c=C()
print c.v()
print super(C, c).v()
print super(B, c).v()

(, , , )
C
B
A 
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-21 Thread Kent Johnson
tiger12506 wrote:
 > Also, does anyone want to clarify? I thought that super() only return 
one of
 > the base classes and was frowned upon for objects using multiple
 > inheritance???

super() returns the next class in method-resolution order. super() was 
added to the language specifically to address some problems introduced 
by multiple inheritance.

http://www.python.org/doc/2.2.3/whatsnew/sect-rellinks.html#SECTION00033

Actually super() doesn't return a class at all, it returns an object of 
type 'super' that is a proxy for the actual class. And the class it 
proxies may not even be an ancestor of the class named as the first 
argument. For example:

class A(object):
 def v(self):
 print 'A'

class B(A):
 def v(self):
 print 'B'
 super(B, self).v()

class C(A):
 def v(self):
 print 'C'
 super(C, self).v()

class D(B, C):
 def v(self):
 print 'D'
 super(D, self).v()

D().v()

prints
D
B
C
A

so super(B, D()) points to C which is not a base class of B at all; it 
*is* the next class after B in D.__mro__ which is
(, , , 
, )

The super() docs are quite inaccurate on this point. There is already an 
issue for this in Roundup that seems to have foundered on how to explain 
some of the finer points of super(). (Hmmm... "If the implementation is 
hard to explain, it's a bad idea." What if it is impossible to explain 
:-) The issue has some suggested improvements for the docs:
http://bugs.python.org/issue1163367


Andreas Kostyrka wrote:
> This way, if all classes use super, they can cooperativly call all
> implementations of a given method.

The key here is "if all classes use super". super() needs to be used 
consistently in an inheritance hierarchy.

> That's the theory. In practice there are a number of pitfalls which
> makes super problematic. ;)

Yes. Here is a fairly lengthy document from the Chandler project about 
the correct way to use super:
http://chandlerproject.org/bin/view/Projects/UsingSuper

The complications lead some people to conclude either that super() is 
either too broken or too complicated to use:
http://fuhm.net/super-harmful/

Guido's response to the above:
http://mail.python.org/pipermail/python-dev/2005-January/050656.html

For myself, I have concluded that super() is difficult to use correctly 
and addresses problems that I have never had in practice, so I don't use it.

Kent
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-21 Thread Andreas Kostyrka
It does not return them at once.

It returns them piece by piece:
[EMAIL PROTECTED]:/tmp> cat mro.py 
class A(object):
v=lambda self: "A"
class B(object):
v=lambda self: "B"
class C(B,A):
v=lambda self: "C"

print C.__mro__

c=C()
print c.v()
print super(C, c).v()
print super(B, c).v()
[EMAIL PROTECTED]:/tmp> python2.5 mro.py 
(, , , )
C
B
A

Andreas

Am Freitag, den 21.03.2008, 23:11 -0500 schrieb tiger12506:
> Woah. Either you're leaving out essential info, or python got a lot more 
> complicated.
> 
> Firstly, super returns all base classes. How? Does it return a tuple of 
> them, or a container object, or is this something horribly worse such as 
> syntactic sugar?
> 
> It doesn't make sense for it to return a tuple, then super().__init__ would 
> call the init method of the tuple, not each class, so then syntactic sugar 
> would have to be involved. I doubt that..
> 
> A container object could use __getattr__ to magically call each of the 
> __init__ methods of the contained class references.
> The most logical is the container object. But that leaves things open for 
> duplicate calls to __init__
> So the container would have to keep track of the base classes it has already 
> called... which might be the ordered list __mro__, but those are class 
> specific, not global, so each super class would not know if an __init__ has 
> been called or not... But then again, you would need duplicate calls because 
> each level of super would need different initiation.
> 
> I apologize. Would you care to explain this a little more technically? 
> Specific and accurate are better than translated into layman's terms. I've 
> been with python for a while now. thanks.
> 
> >Actually, super returns all base classes, all in it's own time.
> >
> >Basically, every class has a member __mro__, that contains a
> >consistently ordered list of classes.
> >
> >super needs the class from where it is being called to locate the right
> >place in the __mro__ and to hand you a wrapper around self for the next
> >base class in this list.
> >
> >This way, if all classes use super, they can cooperativly call all
> >implementations of a given method.
> >
> >That's the theory. In practice there are a number of pitfalls which
> >makes super problematic. ;)
> >
> >Andreas 
> ___
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-20 Thread tiger12506
Woah. Either you're leaving out essential info, or python got a lot more 
complicated.

Firstly, super returns all base classes. How? Does it return a tuple of 
them, or a container object, or is this something horribly worse such as 
syntactic sugar?

It doesn't make sense for it to return a tuple, then super().__init__ would 
call the init method of the tuple, not each class, so then syntactic sugar 
would have to be involved. I doubt that..

A container object could use __getattr__ to magically call each of the 
__init__ methods of the contained class references.
The most logical is the container object. But that leaves things open for 
duplicate calls to __init__
So the container would have to keep track of the base classes it has already 
called... which might be the ordered list __mro__, but those are class 
specific, not global, so each super class would not know if an __init__ has 
been called or not... But then again, you would need duplicate calls because 
each level of super would need different initiation.

I apologize. Would you care to explain this a little more technically? 
Specific and accurate are better than translated into layman's terms. I've 
been with python for a while now. thanks.

>Actually, super returns all base classes, all in it's own time.
>
>Basically, every class has a member __mro__, that contains a
>consistently ordered list of classes.
>
>super needs the class from where it is being called to locate the right
>place in the __mro__ and to hand you a wrapper around self for the next
>base class in this list.
>
>This way, if all classes use super, they can cooperativly call all
>implementations of a given method.
>
>That's the theory. In practice there are a number of pitfalls which
>makes super problematic. ;)
>
>Andreas 
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-20 Thread Andreas Kostyrka

Am Freitag, den 21.03.2008, 21:48 -0500 schrieb tiger12506:

Actually, super returns all base classes, all in it's own time.

Basically, every class has a member __mro__, that contains a
consistently ordered list of classes.

super needs the class from where it is being called to locate the right
place in the __mro__ and to hand you a wrapper around self for the next
base class in this list.

This way, if all classes use super, they can cooperativly call all
implementations of a given method.

That's the theory. In practice there are a number of pitfalls which
makes super problematic. ;)

Andreas

> Also, does anyone want to clarify? I thought that super() only return one of 
> the base classes and was frowned upon for objects using multiple 
> inheritance??? 
> ___
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-20 Thread tiger12506
>> class SubClass(BaseClass):
>> def __init__(self, t, *args, **kw):
>> super(SubClass, self).__init__(*args, **kw)
>> # do something with t

> Is there a proper way to handle the case when SubClass() is called using 
> positional arguments, and you do not desire "t" to be at the beginning?

Sorry. If you are using *args and **kw then t has to be at the beginning. 
Hmm... Unless you consider t to be part of *args or **kw, then you could 
process those before the call to super's __init__. After the def and before 
the call to the super's __init__, *args and **kw are just a list and a 
dictionary. You can edit them however you wish. ;-)

Also, does anyone want to clarify? I thought that super() only return one of 
the base classes and was frowned upon for objects using multiple 
inheritance??? 
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-19 Thread Allen Fowler

> Nowadays the best practice for invoking a method from all superclasses
> (yes, multiple inheritance) is this:
> 
> class SubClass(BaseClass):
> def __init__(self, t, *args, **kw):
> super(SubClass, self).__init__(*args, **kw)
> # do something with t
> 
> That way you let Python decide which superclasses your SubClass has,
> instead of hard-coding it in several places.
>

Excellent.  Thank you.  This seems far more logical.

Is there a proper way to handle the case when SubClass() is called using 
positional arguments, and you do not desire "t" to be at the beginning?

Thanks again,
:)





  

Be a better friend, newshound, and 
know-it-all with Yahoo! Mobile.  Try it now.  
http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-18 Thread Allen Fowler

> >  What's the most "pythonic" way to make this work?
> 
> class BaseClass(object):
>   def __init__(self, x, y, z, foo='foo'): # whatever
>  # etc
> 
> class SubClass(BaseClass):
>   def __init__(self, t, *args, **kw):
> BaseClass.__init__(self, *args, **kw)
> # do something with t
> 
> This does mean that the special sub class argument has to come before
> the base class arguments when you create instances.
> 
> Whether you call BaseCla

Thank you...  Excellent idea.  

I haven't tried it yet, but I suppose **kwarg.pop()'ing  and *args manipulation 
could help ease subclass instantiation call signature limitations. (?)

Thanks,
:)



  

Looking for last minute shopping deals?  
Find them fast with Yahoo! Search.  
http://tools.search.yahoo.com/newsearch/category.php?category=shopping

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-18 Thread Allen Fowler

> > class MySubClass(MySuperClass):
> > 
> > def __init__(self, just_a_sub_option):  # what about other args? **args?
> 
> I think I would go ahead and list the superclass parameters and put the 
> new one at the end:
>  def __init__(self, opt_1, opt_2, opt_3, opt_n, just_a_sub_option):
> 
> > MySuperClass.__init__()# Should this be first?  
> What args to use? **args?
> 
> MySuperClass.__init__(self, opt_1, opt_2, opt_3, opt_n)
> 
> John's method will also work but I prefer to add the new parameter at 
> the end of the argument list.


(Hmm.. I should have pointed out that I generally use keyword args.  )

Right. So, I can certainly call the MySuperClass.__init__() with a long list of 
kwargs, but that gets annoying quickly when the superclass is also under active 
development and it's call signature frequently changes. 






  

Never miss a thing.  Make Yahoo your home page. 
http://www.yahoo.com/r/hs

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-18 Thread Luciano Ramalho
Nowadays the best practice for invoking a method from all superclasses
(yes, multiple inheritance) is this:

class SubClass(BaseClass):
def __init__(self, t, *args, **kw):
super(SubClass, self).__init__(*args, **kw)
# do something with t

That way you let Python decide which superclasses your SubClass has,
instead of hard-coding it in several places.

Cheers,

Luciano


On Tue, Mar 18, 2008 at 9:37 PM, John Fouhy <[EMAIL PROTECTED]> wrote:
> On 19/03/2008, Allen Fowler <[EMAIL PROTECTED]> wrote:
>  >  I have a super class that accepts many arguments to it's constructor, and 
> a subclass that should define one additional argument.
>  >
>  >  What's the most "pythonic" way to make this work?
>
>  class BaseClass(object):
>   def __init__(self, x, y, z, foo='foo'): # whatever
>  # etc
>
>  class SubClass(BaseClass):
>   def __init__(self, t, *args, **kw):
> BaseClass.__init__(self, *args, **kw)
> # do something with t
>
>  This does mean that the special sub class argument has to come before
>  the base class arguments when you create instances.
>
>  Whether you call BaseClass.__init__ early or late in the subclass init
>  method could depend on what your classes are doing.  Remember, in
>  Python, __init__ only initializes objects, it doesn't create them.
>  It's just another bit of code that you can call whenever you want.
>
>  --
>  John.
>
>
> ___
>  Tutor maillist  -  Tutor@python.org
>  http://mail.python.org/mailman/listinfo/tutor
>
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-18 Thread Kent Johnson
Allen Fowler wrote:

> What's the most "pythonic" way to make this work?
> 
> class MySuperClass(object):
> 
> def __init__(self, opt_1, opt_2, opt_3, opt_n):
># stuff done here
> pass
> 
> 
> class MySubClass(MySuperClass):
> 
> def __init__(self, just_a_sub_option):  # what about other args? **args?

I think I would go ahead and list the superclass parameters and put the 
new one at the end:
 def __init__(self, opt_1, opt_2, opt_3, opt_n, just_a_sub_option):

> MySuperClass.__init__()# Should this be first?  
> What args to use? **args?

MySuperClass.__init__(self, opt_1, opt_2, opt_3, opt_n)

John's method will also work but I prefer to add the new parameter at 
the end of the argument list.

Kent
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Calling super classs __init__?

2008-03-18 Thread John Fouhy
On 19/03/2008, Allen Fowler <[EMAIL PROTECTED]> wrote:
>  I have a super class that accepts many arguments to it's constructor, and a 
> subclass that should define one additional argument.
>
>  What's the most "pythonic" way to make this work?

class BaseClass(object):
  def __init__(self, x, y, z, foo='foo'): # whatever
 # etc

class SubClass(BaseClass):
  def __init__(self, t, *args, **kw):
BaseClass.__init__(self, *args, **kw)
# do something with t

This does mean that the special sub class argument has to come before
the base class arguments when you create instances.

Whether you call BaseClass.__init__ early or late in the subclass init
method could depend on what your classes are doing.  Remember, in
Python, __init__ only initializes objects, it doesn't create them.
It's just another bit of code that you can call whenever you want.

-- 
John.
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor