Solved

python subclass with extra arguments?

Posted on 2013-10-23
7
1,410 Views
Last Modified: 2013-10-25
Hi,

I'm trying to figure out Python's subclassing when the subclass requires additional arguments.  I've put together a very simple program just to try things out, but I can't seem to get the syntax Python likes.
class Abc(object):

    def __init__(self,a,b,c=None):
        self.a = a
        self.b = b
        self.c = c

    def pr(self):
        print "{}, {}, {}".format(self.a,self.b,self.c)

Open in new window

#------------------Different file
import abc_class as ac

class Abcd(ac.Abc):

    def __init__(self, a,b,c,d):  #What goes here for a, b, c and d?

       # Tried everything here.  What's this super call supposed to look?
        super( Abcd, self,a).__init__()like?

if __name__ == '__main__':

    x = Abcd(4,5,6)
    x.pr()

Open in new window

I subclassed Abc from object because I read something about old vs. new style classes and the new style require the base class object (I'm obviously no expert ...)

I need to instantiate the Abcd class, which should call the super's init and use the extra arguments for additional processing.  However, no matter how many arguments I add or remove, it always says I'm giving too many or too few.

What's the syntax if I want the Abcd class to have an argument 'd' in addition to a,b and c and call the super's init with a, b and c?

Thanks!
0
Comment
Question by:ugeb
  • 3
  • 3
7 Comments
 
LVL 28

Accepted Solution

by:
pepr earned 500 total points
ID: 39596539
There can be several approaches to your problem. Firstly, it depends on whether you need to use a specific version of Python.

Looking at the syntax, you are using Python 2.7 (or you should use). Then you should write it like:
class Base(object):

    def __init__(self, a, b, c=None):
        self.a = a
        self.b = b
        self.c = c

    def pr(self):
        print '{}, {}, {}'.format(self.a, self.b, self.c)
        
        
class Derived(Base):

    def __init__(self, a, b, c, d):
         super(Derived, self).__init__(a, b, c)
         self.d = d       
         
    def pr(self):
        print '{}, {}, {}, {}'.format(self.a, self.b, self.c, self.d)
        
        
if __name__ == '__main__':
    
    bas = Base(1, 2, 3)
    bas.pr()
    
    der = Derived(1, 2, 3, 4)
    der.pr()  

Open in new window

However, the Python 3 removes the visibility of the term "new-style classes", and does not force you to use object as a base class. All classes are of new-style, but the syntax is as simple as in the Python 2 old-style. Also the super() can be used more elegantly -- it does not require any argument. Notice also, that it is better to define your own __str__() method implementation and use the print command for the object instead of calling the .pr() method of the object. Then you can redefine the __str__ of the derived class using the result of __str__ from the base class. (This holds also for Python 2.):
class Base:

    def __init__(self, a, b, c=None):
        self.a = a
        self.b = b
        self.c = c

    def __str__(self):
        return '{}, {}, {}'.format(self.a, self.b, self.c)

        
class Derived(Base):

    def __init__(self, a, b, c, d):
         super().__init__(a, b, c)    # pass the to the Base initializer
         self.d = d                   # add the extra variable
         
    def __str__(self):
        # Here string representation of the Base part with added self.d
        return super().__str__() + ', {}'.format(self.d) 

        
if __name__ == '__main__':
    
    bas = Base(1, 2, 3)
    print(bas)
    
    der = Derived(1, 2, 3, 4)
    print(der)      

Open in new window

If you still need to use Python 2.7, then I recommend not to use super(), use the old style classes and name the base class explicitly:
class Base:

    def __init__(self, a, b, c=None):
        self.a = a
        self.b = b
        self.c = c

    def __str__(self):
        return '{}, {}, {}'.format(self.a, self.b, self.c)


class Derived(Base):

    def __init__(self, a, b, c, d):
         Base.__init__(self, a, b, c)
         self.d = d

    def __str__(self):
        # Here string representation of the Base part with added self.d
        return Base.__str__(self) + ', {}'.format(self.d)


if __name__ == '__main__':

    bas = Base(1, 2, 3)
    print bas

    der = Derived(1, 2, 3, 4)
    print der

Open in new window

Feel free to ask what is not understandable.
0
 
LVL 16

Expert Comment

by:gelonida
ID: 39597335
minor comment:

you can also use new style classes (so Base inherits from object)
and not use super()

so:
class Base(object):
. . . 

class  Derived(Base):
    def __init__(self, a, b, c, d):
         Base.__init__(self, a, b, c)

Open in new window

0
 
LVL 28

Expert Comment

by:pepr
ID: 39597430
I agree, but why would I use object explicitly? There should be a specific reason for making things more complicated.
0
Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

 
LVL 16

Expert Comment

by:gelonida
ID: 39597633
a few reasons (though in many cases they don't really matter, but well . . ):
- in order to avoid any subtle differences in behaviour which one might forget / overlook.
   ( special methods / descriptors / method resolution order in case of multiple inheritance )
- Python 3 will only have the behaviour of old style classes
- decorators like @classmethod and @staticmethod
- just out of habit ;-)
- for consistency reasons

What can also be annoying is if you want to inherit from an old style class and suddenly some features don't work  (descriptors) in derived classes.

At least in our team (using Python 2.7) we don't use any old style classes for our own code
as is the official recommendation.
0
 
LVL 11

Author Closing Comment

by:ugeb
ID: 39598177
Yes indeed it is Python 2.7 and your solution works well.  Thanks to both!
0
 
LVL 28

Expert Comment

by:pepr
ID: 39599790
why would I use object explicitly?
- Python 3 will only have the behaviour of old style classes

The official documentation says for Python 3 (http://docs.python.org/3/reference/compound_stmts.html#class-definitions)
Classes without an inheritance list inherit, by default, from the base class object; hence,

class Foo:
    pass

is equivalent to

class Foo(object):
    pass

0
 
LVL 16

Expert Comment

by:gelonida
ID: 39599799
- Python 3 will only have the behaviour of old style classes

was a typo.
I wanted to write" new style" of course.
Thus in order to have most similiar behaviour for code potentially running on 2.7 and 3.0 I always inherit from object .


Whatever. As I said in my previous post. in most real life cases it won't make a difference.
I'm just being very conservative.
0

Featured Post

ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Eclipse Neon start with Admin account only 6 125
Turning python script into an applet 12 111
Apps blocked by Java 9 79
Does python 2.7 include encryption library by default? 2 21
This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
Learn the basics of if, else, and elif statements in Python 2.7. Use "if" statements to test a specified condition.: The structure of an if statement is as follows: (CODE) Use "else" statements to allow the execution of an alternative, if the …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question