Reputation: 4328
I am a newbie in python and trying my hands in oops programming here.
I am initializing base class constructor in derived class , but when trying to print its attribute in base class it gives me errorobject has no attribute
import random
import os
import sys
class Animal:
__name =""
def __init__(self,name):
self.__name = name
def toString(self):
return "{} is the animal name".format(self.__name)
def get_name(self):
return self.__name
cat = Animal("natasha")
print (cat.toString())
class Dog(Animal):
__owner = ""
def __init__(self,name,owner):
self.__owner= owner
#Animal.__init__(self,name)
super(Dog, self).__init__(name)
def toString(self):
return "{} is Animal. And owner is: {}".format(self.__name,self.__owner)
rocky = Dog("rocky","Ronchi")
print (rocky.toString())
What am i doing wrong here ? I tried like calling super.get_name()
also which was a getter function instead of self.__name
but this also did not work.I am working on python3.4
Upvotes: 0
Views: 80
Reputation: 33
Actually if you know the concept of abstraction, you've give the name in the parent class as a private key.
import random
import os
import sys
class Animal:
__name =""
def __init__(self,name):
self._name = name
def toString(self):
return "{} is the animal name".format(self._name)
def get_name(self):
return self._name
cat = Animal("natasha")
print (cat.toString())
class Dog(Animal):
__owner = ""
def __init__(self,owner,*args):
super(Dog, self).__init__(*args)
self.__owner= owner
def String(self):
return "{} is Animal. And owner is: {}".format(self._name,self.__owner)
rocky = Dog("rocky","Ronchi")
print (rocky.String())
this is the same code as yours but with little correction, just check it
Upvotes: 0
Reputation: 307
Replace your method get_name
of Animal
with the following code
@property
def name(self):
return self.__name
Also remember to update the toString
of Dog
to
def toString(self):
return "{} is Animal. And owner is: {}".format(self.name,self.__owner)
There're some things that I think it's worth point out if you're new to Python:
@property
and @property.setter
decorators instead of the get_something
/set_something
conventions in language such as Java.toString
is also not very Pythonic. First, method names should be in snake_case
. Second, define a method with the signature def __str__(self)
and return a str
. Then you'll be able to do print(rocky)
without having to call the __str__
as you do for toString
.super
in Python 3 is just super()
, with no arguments passed (https://docs.python.org/3/library/functions.html#super).Upvotes: 2
Reputation: 148965
Variables starting with double underscores are said as private. They are mangled so they cannot be used in subclasses. Using CPython 3.5, you can confirm it simply with:
>>> rocky.__dict__
{'_Animal__name': 'rocky', '_Dog__owner': 'Ronchi'}
>>>
When called from Dog
class, self.__name
searches a _Dog__name
attribute and cannot find it.
There are two common ways do deal with it:
use the getter from base class:
def toString(self):
return "{} is Animal. And owner is: {}".format(self.get_name(),self.__owner)
This correctly gives:
>>> print(rocky.toString())
rocky is Animal. And owner is: Ronchi
>>>
Upvotes: 0
Reputation: 599610
This is why you must not use double-underscore prefixes for your instance attributes. These are name mangled, and almost never do what you expect.
Just use self.name
and self.owner
everywhere.
Upvotes: 2