Trouble understanding python inheritance arguments - python

I've tried reading a few different tutorials, but I still can't figure it out. I have two simple classes. Animal and cat.
class Animal:
def __init__(self, name):
self.name = name
class Cat(Animal):
def __init___(self, age):
self.age = age
print('age is: {0}'.format(self.age))
def talk(self):
print('Meowwww!')
c = Cat('Molly')
c.talk()
Output is:
Meowwww!
The code runs, but I'm a little confused. I created an instance of the cat class with c = Cat('Molly'). So somehow by using "Molly" as an argument for the Cat() class instance, it feeds "Molly" to the original base class (Animal) instead of the Cat class instance I created? Why? So how do I feed the Cat class instance the age variable it requires?
I tried doing:
c = Cat('Molly', 10)
But it complains about too many arguments. And secondly, why doesn't the __init__ function of the Cat class get called? It should print "age is...". It just never does.
EDIT: Got it to work, thanks to Martijn Pieters! Here is the updated code (works with python3):
class Animal():
def __init__(self, name):
self.name = name
print('name is: {0}'.format(self.name))
class Cat(Animal):
def __init__(self, name, age):
super().__init__(name)
self.age = age
print('age is: {0}'.format(self.age))
def talk(self):
print('Meowwww!')
c = Cat('Molly', 5)
c.talk()

You misspelled __init__:
def __init___(self, age):
# 12 345
That's 3 double underscores at the end, not the required 2.
As such, Python won't call it as it is not the method it is looking for.
If you want to pass in both age and name, give the method another argument, then call the parent __init__ with just the name:
class Cat(Animal):
def __init__(self, name, age):
super().__init__(name)
self.age = age

Related

unpack from parent class

So I have been making an RPG game and run into some troubles with inheritance and unpacking.
I have tried to make a simple version of the problem I am having:
class Animal():
def __init__(self,name):
self.name = name
def say_noise(self):
noise = "I am an animal"
by_who = "Animal"
return noise,by_who
class Dog(Animal):
def __init__(self,name):
self.name = name
def say_noise(self):
Animal.say_noise(self)
animal = Animal("man")
doggy = Dog("name")
What I want to do is return the same 2 things in the Animal class and the Dog class.
Now when I do say_noise() with my Animal it works fine, as it returns:
('I am an animal', 'Animal')
However, it does not return anything when I do it with the Dog class, and I tried unpacking them as well (which is what I aim to do in my real code), but when I do this.
a,b =doggy.say_noise()
it just returns this:
TypeError: cannot unpack non-iterable NoneType object
How can I return the same thing with the same class method, by only inheriting it from the parent class?
It's because you are not returning anything from Dog classes say_noise method.
Update your code like this,
class Animal():
def __init__(self, name):
self.name = name
def say_noise(self):
noise = "I am an animal"
by_who = "Animal"
return noise, by_who
class Dog(Animal):
def __init__(self, name):
self.name = name
def say_noise(self):
return Animal.say_noise(self)
animal = Animal("man")
doggy = Dog("name")
a, b = doggy.say_noise()

After inheriting a function how to give it more parameters

I inherited a student class for my masters_student class and and all the functions are working as expected but I want to give my masters_student class another parameter called Age.
How could I do that?
class masters_student(student , age):
self.age = age
def qualify(self):
if self.Gpa > 3.0 :
print("You qualify for the masters Programme")
else:
print("you dont qualify for Masters programme")
Then it shows a error
class student:
def __init__(self, name, major, Gpa, loan):
self.name = name
self.major = major
self.Gpa = Gpa
self.loan = loan
def On_honour_roll(self):
if self.Gpa >= 3.5:
return True
else:
return False
class masters_student(student):
def qualify(self):
if self.Gpa > 3.0 :
print("You qualify for the masters Programme")
else:
print("you dont qualify for Masters programme")
Here is some documentation on [https://rhettinger.wordpress.com/2011/05/26/super-considered-super/][super].
You need to tell python how to instantiate you children class following parent one.
class master_student(student):
def __init__(self, name, major, Gpa, loan, age):
super(student, self).__init__(name, major, Gpa, loan)
self.age = age
This should work.
First, we have to get our terminology correct. I don't see where you are taking an existing function that you are inheriting and then redefining it to have additional parameters. When you code:
class masters_student(student , age):
You are specifying multiple inheritance, that is, you are saying that class masters_student inherits from both class student and from class age. But then on the next line you code:
self.age = age
which does not make too much sense.
It seems that what you are trying to do is add to your new class, masters_student, an additional data attribute named age. I can't even be sure of that because I never see in your question any code that references age; I would have thought that it would be used in method qualify. But assuming that is your intent, there are several ways of doing this depending on whether you are running Python 3 or Python 2. The simplest way, which works on either Python 2 or Python 3 would be:
class masters_student(student):
def __init__(self, name, major, Gpa, loan, age):
student.__init__(self, name, major, Gpa, loan) # initialize the base class
self.age = age
If you are running Python 3, you can also code:
class masters_student(student):
def __init__(self, name, major, Gpa, loan, age):
super().__init__(name, major, Gpa, loan) # initialize the base class
self.age = age
If you are running Python 2 (or Python 3), you can also code:
class masters_student(student):
def __init__(self, name, major, Gpa, loan, age):
super(masters_student, self).__init__(name, major, Gpa, loan) # initialize the base class
self.age = age
But, you must ensure that your base class, student in this case, inherits from class object:
class student(object):
When you use super() to initialize base classes, the base classes, too, must use super() to initialize their base and sibling classes.

Why can't I add another variable in the class using setter and getter?

I wrote a class called person and used setter and getter. At first, the code was working fine when I used one variable.However when I added another variable , it said that 2 required positional arguments were missing:"name" and "age".
class person:
def __init__(self, name, age):
self.name = name
self.age = age
def set_name(self,y):
self.name = y
def get_name(self):
return self.name
def set_age(self,x):
self.age = x
def get_age(self):
return self.age
p1 = person()
p1.set_name("Armeen")
p1.set_age("20")
print(p1.get_age())
print(p1.get_name())
Your __init__ method takes two arguments namely name and age. You aren't providing any argument when creating an instance of Person. So you may want to do the following:
p1 = person('Armeen', 20)
As opposed to
p1 = person()
Or if you want to allow user not to specify name and age at the time of instance creation, you can set those parameter as optional by doing the following change in __init__
def __init__(self, name = None, age = None): ##This would work with your code as well

Return subclass when calling parent class

I want to get instance of one of subclasses when trying get instance of a superclass (parent class) depending on arguments. For example, I have parent class(I'm using python3):
class Man:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print("Hello! My name is {}.".format(self.name))
And subclass:
class YoungMan(Man):
def say_hello(self):
print("Hey, man! Wazap?")
If age of Man less 30, I want it become YoungMan:
John = Man('John', 25)
type(John) #<class '__main__.YoungMan'>
John.say_hello() #Hey, man! Wazap?
I tried solve it with Man.__new__():
class Man:
def __new__(cls, name, age):
if age < 30:
return YoungMan(name, age)
else:
return super(Man, cls).__new__()
...
But John.say_hello() returns Hello! My name is John. So Man methods override YoungMan methods. After I tried use metaclass for Man:
class ManFactory(type):
def __call__(self, name, age):
if age < 30:
return YoungMan(name, age)
class Man(metaclass=ManFactory):
...
But it lached on ManFactory.__call__().
I understand that I can use a funtion John = get_Man(name, age) which returns right class, but it isn't so handsome. My question is about how do it like this:
John = Man('John', 25)
type(John) #<class '__main__.YoungMan'>
John.say_hello() #Hey, man! Wazap?
Brad = Man('Brad', 54)
type(Brad) #<class '__main__.Man'>
Brad.say_hello() #Hello! My name is Brad.
Not sure if this is good practice but you could set self.__class__:
class Man:
def __init__(self, name, age):
if age < 30: self.__class__ = YoungMan
self.name = name
self.age = age
def say_hello(self):
print("Hello! My name is {}.".format(self.name))
class YoungMan(Man):
def say_hello(self):
print("Hey, man! Wazap?")
a = Man("Brad", 15)
print(type(a))
>>><class '__main__.YoungMan'>
a.say_hello()
>>>Hey, man! Wazap?
The main problem with this method is that the YoungMan would still be constructed by Man.__init__() so the classes would have to be compatible. Creating a function get_man() is still the best solution.

Python Class Pet Program

I am working on an assignment for Python Programming 157 at my school.
I need to write a class called Pet that has the following data attributes:
__name (for the name of the pet)
__animal_type (Examples: "Cat", "Dog", and "Hamster" )
__age (for the pet's age)
__height (for the pet's height)
It needs to include
set_name
get_name
I have tried like 4 times and cannot seem to get it right... any clues on getting it started?
# The Pet Program.
class PetProgram:
# The __init__ method accepts an argument for the program
# and adds it to the __pets attribute.
def __init__(self, pet):
self.__pets = pet
# The name will add to the pet attribute.
def name(self, name):
self.__pets = name
def age(self, age):
self.__pets = age
def animal(self, animal):
self.__pets = animal
def height(self, height):
self.__pets = height
# The pets_return will show you the list.
def pets_return(self):
return self.__pets
# The Pet Program.
import petsprogram
def main():
# Enter the name.
petname = input('What is the name of the pet: ')
print 'This will be added to the record.'
savings.name(petname)
# Display the list.
print petsprogram
main()
Above is my latest try...no such luck...any help? Thanks in advance...
A class is not a program, a class should model a thing, like a pet. Therefore, to start off, you should name your class appropriately.
class Pet(object): # Pet derives from the object class, always do this
Now I think you want a constructor that takes the name of the pet, and perhaps the type of pet as well, so we'll define that.
def __init__(self, pet_name, pet_type):
self.pet_name = pet_name
self.pet_type = pet_type
You also need a get and set for the name:
def get_name(self):
return self.pet_name
def set_name(self, pet_name):
self.pet_name = pet_name
To use this class, you instantiate it into an instance of the class:
puppy = Pet('Rover', 'Dog')
puppy.get_name() # prints Rover
I hope that's enough to get you going. You should read up on OOP in Python as mentioned in the comments.
First, why are you using "private" __attributes? That doesn't seem warranted.
Second, you're assigning all your properties to the same instance variable:
self.__pets = pet
self.__pets = name
self.__pets = age
self.__pets = animal
self.__pets = height
You should be using something like
def __init__(self, pet, name, age, animal, height):
self.pet = pet
self.name = name
self.age = age
self.animal = animal
self.height = height
and you should definitely read the tutorial on classes before venturing any further.
I'm not sure where the __pets binding comes into play. Your initial description doesn't say anything about that. I would not have expected an object that represents a pet, as in, a singular pet, to have an attribute that was a list of pets. I would expect something like:
class PetProgram:
def __init__(self, name ='', age=0, type='Unknown', height=0):
self.__name = name
self.__age = age
self.__animal_type = type
self.__height = height
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
I'm also not sure where the imports petprogram comes from... is that perchance what your supposed to call your module, and then the instructor has provided that as something you're supposed to run to test it?
(also, what's with all the __under_scores? is this something your teacher is encouraging?)
How does something like this look?
>>> class Pets:
def set_Name(self,name):
self.name=name
def get_Name(self):
return self.name
def set_Atype(self,atype):
self.atype=atype
def get_Atype(self):
return self.atype
def set_Age(self,age):
self.age=age
def get_Age(self):
return self.age
def set_Height(self,height):
self.height=height
def get_Height(self):
return self.height

Categories