Solved

python subclass with extra arguments?

Posted on 2013-10-23
7
1,481 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 29

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 29

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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
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 29

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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…

861 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