Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder1.enfer-du-nord.net!newsfeed.eweka.nl!eweka.nl!feeder3.eweka.nl!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'argument': 0.04; 'classes,': 0.05; 'arguments': 0.07; 'class,': 0.07; 'suppose': 0.07; '**kwargs):': 0.09; '__init__': 0.09; 'appropriate.': 0.09; 'inherited': 0.09; 'positional': 0.09; 'sep': 0.09; 'whichever': 0.09; 'def': 0.10; 'library': 0.15; 'sat,': 0.15; '"making': 0.16; '*should*': 0.16; 'argument.': 0.16; 'inheritance': 0.16; 'missing,': 0.16; 'mro': 0.16; 'sorts': 0.16; 'two,': 0.16; 'wrote:': 0.17; 'detect': 0.17; 'instance,': 0.17; 'changes': 0.20; 'written': 0.20; 'together.': 0.21; 'strip': 0.22; 'header :In-Reply-To:1': 0.25; '[1]': 0.27; 'functions.': 0.27; 'timely': 0.27; 'message-id:@mail.gmail.com': 0.27; "doesn't": 0.28; 'arguments.': 0.29; 'complain': 0.29; "d'aprano": 0.29; 'falls': 0.29; 'methods.': 0.29; 'optional': 0.29; 'signatures': 0.29; 'steven': 0.29; 'skip:_ 10': 0.29; 'class': 0.29; 'this.': 0.29; 'classes': 0.30; 'normally': 0.30; 'could': 0.32; 'to:addr:python- list': 0.33; 'received:google.com': 0.34; 'whatever': 0.35; 'expected': 0.35; 'pm,': 0.35; 'subject:?': 0.35; 'received:209.85': 0.35; 'there': 0.35; 'but': 0.36; 'method': 0.36; 'should': 0.36; 'one,': 0.37; 'two': 0.37; 'being': 0.37; 'received:209': 0.37; 'subject:: ': 0.38; 'perform': 0.38; 'object': 0.38; 'sure': 0.38; 'to:addr:python.org': 0.39; 'header:Received:5': 0.40; 'your': 0.60; 'most': 0.61; 'first': 0.61; 'ever': 0.63; 'making': 0.64; 'to,': 0.65; 'receive': 0.71; 'manner': 0.74; "class's": 0.84; 'off,': 0.84; 'subject:always': 0.84; 'to:name:python': 0.84; 'cooperative': 0.91; 'subject:add': 0.91; 'inheritance,': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=myCc5XdPSiA64kn2TSoUzjyFsdAmIPOl94c5NsVFE5U=; b=WYTnakm4I2DdDyqjIE08m96dYqJ1qdFHVOo4h949GleRvpZcNN6B5eUdjjnLMCfLZI nqt6C2Qx7ZSQALWIigwGNWp3fEQ9jNr81rNih4b3C0KnIis4Hsxjt+2w00+Nm2/CkRXa m34OxGw7RiYNk9FCuBwwkZ2EGkZdNpFrn3a0NTpFx4DpmDfoHgpWLjcNMG+b130l/Chs JgvclgysY9Go58r+p2Y/y2N3GPECjgq4BbvI3y5M8bw//gO8R2bVtU+jxtbMlM0AEuIe 04nPjpgvoaPzD1BeNhFfEDllkVjGMX35XPR+PXUru5HJVFjwyznFxR3R5ZPZSOimHjIB PLhg== MIME-Version: 1.0 In-Reply-To: <5067cc81$0$29981$c3e8da3$5496439d@news.astraweb.com> References: <50672d20$0$29981$c3e8da3$5496439d@news.astraweb.com> <5067cc81$0$29981$c3e8da3$5496439d@news.astraweb.com> From: Ian Kelly Date: Sun, 30 Sep 2012 01:13:16 -0600 Subject: Re: Should one always add super().__init__() to the __init__? To: Python Content-Type: text/plain; charset=ISO-8859-1 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 49 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1348989229 news.xs4all.nl 6900 [2001:888:2000:d::a6]:56763 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:30545 On Sat, Sep 29, 2012 at 10:37 PM, Steven D'Aprano wrote: > [1] You *should* call super, unless you have an excellent reason not to, > so that your class doesn't break multiple-inheritance. But you need to do > so with care making sure that the argument signatures are designed for > cooperative use of super. I disagree. Most classes will not ever be used for multiple inheritance, and the changes involved in "making sure that the argument signatures are designed for cooperative use of super" are not trivial. For one, it means not being able to use positional arguments in __init__ methods. For two, the receive-and-strip-off-keyword-arguments approach falls apart if you have unrelated classes that take the same arguments. For illustration, suppose you have the following two classes, both of which use a required Frobnik object to perform their functions. class A: def __init__(self, frobnik, **kwargs): super().__init__(**kwargs) self._frobnik = frobnik ... class B: def __init__(self, frobnik, **kwargs): super().__init__(**kwargs) self._frobnik = frobnik ... Even though these classes have been designed to be cooperative, they cannot be inherited together. Whichever class is first in the MRO will receive the frobnik argument and strip it off, and then the other class's __init__ method will complain of a missing required argument. There are solutions to this. For instance, you could make frobnik optional in each class, each one relying on the other to receive the frobnik argument if it is missing, but this complicates the implementations and makes it difficult to detect in a timely manner if the frobnik argument has actually not been supplied. Or you could change the name of the argument in one of the classes, but then your library users will complain of inconsistent naming. What it boils down to is that classes that are expected to be used for multiple inheritance should be designed to use super cooperatively, but the majority of classes that you write should not have to deal with these sorts of restrictions. Classes that will only ever be singly inherited should be written normally and using whatever superclass call style feels most appropriate.