Re: [Tutor] Calling super classs __init__?
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__?
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__?
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__?
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__?
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__?
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__?
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__?
>> 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__?
> 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__?
> > 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__?
> > 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__?
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__?
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__?
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