python subclass with extra arguments?

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!
LVL 11
ugebAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
peprConnect With a Mentor Commented:
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
 
gelonidaCommented:
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
 
peprCommented:
I agree, but why would I use object explicitly? There should be a specific reason for making things more complicated.
0
A proven path to a career in data science

At Springboard, we know how to get you a job in data science. With Springboard’s Data Science Career Track, you’ll master data science  with a curriculum built by industry experts. You’ll work on real projects, and get 1-on-1 mentorship from a data scientist.

 
gelonidaCommented:
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
 
ugebAuthor Commented:
Yes indeed it is Python 2.7 and your solution works well.  Thanks to both!
0
 
peprCommented:
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
 
gelonidaCommented:
- 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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.