Solved

python subclass with extra arguments?

Posted on 2013-10-23
7
1,209 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
Comment Utility
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
Comment Utility
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
Comment Utility
I agree, but why would I use object explicitly? There should be a specific reason for making things more complicated.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 16

Expert Comment

by:gelonida
Comment Utility
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
Comment Utility
Yes indeed it is Python 2.7 and your solution works well.  Thanks to both!
0
 
LVL 28

Expert Comment

by:pepr
Comment Utility
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
Comment Utility
- 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

The purpose of this article is to demonstrate how we can use conditional statements using Python.
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.
Learn the basics of lists in Python. Lists, as their name suggests, are a means for ordering and storing values. : Lists are declared using brackets; for example: t = [1, 2, 3]: Lists may contain a mix of data types; for example: t = ['string', 1, T…
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 …

763 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now