G M
G M

Reputation: 22449

How to define a method so that return the instance of the current class not of the class where it was inherited in Python?

I am trying Overloading an operator forcing it to return an object of the same instance of the current class not the parent class where the method was overloaded.

class Book:
    def __init__(self,name,pages):
        self.name=name
        self.pages=pages

    def __add__(self,other):
        return Book(self.name,(self.pages + other.pages))


class Encyclopedia(Book):
    def __init__(self,name,pages):
        Book.__init__(self,name,pages)


a=Encyclopedia('Omina',234)
b=Encyclopedia('Omnia2',244)
ab=a+b
print ab

Out: <__main__.Book instance at 0x1046dfd88>

For instance in this case I would like to return an Encycolpedia instance (not a Book instance) without overloading another time the operator __add__ with the same line with Encyclopedia instead of Book I have tried:

return self(self.name,(self.pages + other.pages))

But it doesn't work.

What if the Class Enclcopedia has another attribute:

class Encyclopedia(Book):
    def __init__(self,name,pages,color):
        Book.__init__(self,name,pages)
        self.color=color

Upvotes: 4

Views: 124

Answers (2)

martineau
martineau

Reputation: 123453

You would need to do it something like this, which overloads the base class's methods (in this case, generally by calling them first and then doing additional processing on the result — although that's not a requirement):

class Book(object):
    def __init__(self, name, pages):
        self.name = name
        self.pages = pages

    def __add__(self, other):
        return Book(self.name, self.pages+other.pages)

    def __str__(self):
        classname = self.__class__.__name__
        return '{}({}, {})'.format(classname, self.name, self.pages)

class Encyclopedia(Book):
    def __init__(self, name, pages, color):
        Book.__init__(self, name, pages)
        self.color = color

    def __add__(self, other):
        tmp = super(Encyclopedia, self).__add__(other)
        return Encyclopedia(tmp.name, tmp.pages, self.color+other.color)

    def __str__(self):
        classname = self.__class__.__name__
        return '{}({!r}, {}, {!r})'.format(classname, self.name, self.pages,
                                         self.color)


a = Encyclopedia('Omina', 234, 'grey')
b = Encyclopedia('Omnia2', 244, 'blue')
ab = a+b
print(ab)  # -> Encyclopedia('Omina', 478, 'greyblue')

Upvotes: 1

Jacob H
Jacob H

Reputation: 876

You could utilize self.__class__ instead of casting to Book. Your original add function should look like:

def __add__(self,other):
    return self.__class__(self.name,(self.pages + other.pages))

Upvotes: 6

Related Questions