'Python class polymorphism

I am practicing polymorphism and the following code returns error

class Animal:
    def talk(self, something):
        print(something)

class Dog(Animal):
    def talk(self):
        super().talk("woof woof")

Bonny = Dog
Bonny.talk()
TypeError: talk() missing 1 required positional argument: 'self'

According to what I learned Bonny should be the self argument so why self is missing?



Solution 1:[1]

You are missing some brackets at Bonny = Dog.

class Animal:
    def talk(self, something):
        print(something)

class Dog(Animal):
    def talk(self):
        super().talk("woof woof")

Bonny = Dog()
Bonny.talk()

EDIT

Since this is my top voted answer at the moment, and still has some activity, and it clearly lacks some explanation, I would like to add some.

Bonny = Dog

Means, Bonny is a reference to the Dog class. It is callable, and would the the instance of Dog. Bonny won't be a type.

Bonny = Dog()

If you would like to call the object like above, you should add the brackets. That means you call the object, and referring to it. Bonny will be a reference.

Also references to object should be lowercase.

bonny = Dog()

Second thing. Since your objects indicates they may contain data corresponding to each object of the same type (2 or more Dog objects), so there is a need for a constructor.

class Dog(Animal):
    def __init__(self, name):
        super(Dog, self).__init__(self)
        self.name = name

    def talk(self):
        super().talk("woof woof my name is {}".format(self.name))

    def __str__(self):
        return self.name

This way you can name your dog, make him say his name, and on print(bonny), also print his name using the __str__ method. But also you need to call the super's (in this case the Animal objects) init function, using the super function, used by the OP.

Class inheritence isn't the easiest thing in Python, since it is not a strongly OO language. But classes are awesome!

Solution 2:[2]

You did not initialize an object, you just created a copy of your Dog class with name Bonny. You can see the difference between Dog() and Dog by printing them.

class Animal():
    pass

print(Animal)   # the result is <class '__main__.Animal'>

print(Animal()) # the result is <__main__.Animal object at 0x037D6A50> 

first line is referring to a class which is named Animal but the second line is an object of class Animal. so if you want to create an object of a class you have to initialize the class (just as the second form). your correct code will be this:

class Animal:
    def talk(self, something):
        print(something)

class Dog(Animal):
    def talk(self):
        super().talk("woof woof")

bonny = Dog()
bonny.talk()

also according to Python Style Guide it's standard to name objects in lowercase.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2