Code for an inheritance diagram in python [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 28 days ago.
Improve this question
I'm learning OOP with python and wanted to write code for an inheritance diagram I found online to practice. This is the diagram:
This is my code:
#parent class that is used to set food and family variables for child classes
class Animal:
def __init__(self,family,food):
self.family = family
self.food = food
def getFamily(self):
return self.family
def setFamily(self,newFamily):
self.family = newFamily
def getFood(self):
return self.food
def setFood(self,newFood):
self.food = newFood
#child class that inherits from Animal class
class Cow(Animal):
def __init__(self,owner, family,food):
self.owner = owner
#use the Animal init function to set the family and food properties
Animal.__init__(self,family,food)
def setOwner(self,newOwner):
self.owner = newOwner
def getOwner(self):
return self.owner
class Lion(Animal):
def __init__(self,family,food):
Animal.__init__(self,family,food)
mooingCow = Cow("Bob", "mammal","grass")
print(Cow.__name__+"'s owner: " + mooingCow.getOwner() + ", family: " + mooingCow.getFamily())
hungryLion = Lion("mammal","humans")
My request is, can anyone comment on the correctness of my solution and help me improve it where I can? Also when I removed the Animal parameter from Cow class definition I expected the code to throw an error as Cow is no longer inheriting from Animal so it should not have access to the properties and methods defined in it, however, the code still executes fine. Please could someone also explain why this is happening to me?
Where I expected the error to happen:
class Cow():
def __init__(self,owner, family,food):
self.owner = owner
#use the Animal init function to set the family and food properties
Animal.__init__(self,family,food) # <--- Where I expected the error to happen

class Animal(object):
def __init__(self,family,food):
self.family = family
self.food = food
def getFamily(self):
return self.family
def setFamily(self,newFamily):
self.family = newFamily
def getFood(self):
return self.food
def setFood(self,newFood):
self.food = newFood
#child class that inherits from Animal class
class Cow(Animal):
def __init__(self,owner, family,food):
self.owner = owner
#use the Animal init function to set the family and food properties
super().__init__(family,food)
def setOwner(self,newOwner):
self.owner = newOwner
def getOwner(self):
return self.owner
class Lion(Animals):
pass
mooingCow = Cow("Bob", "mammal","grass")
print(Cow.__name__+"'s owner: " + mooingCow.getOwner() + ", family: " + mooingCow.getFamily())
hungryLion = Lion("mammal","humans")
You can define class Animals as an object to make it a parent class, and you can remove Animal parameter from the Cow class definition, as python will automatically inherit the parent class.
If the Animal class is defined before the Cow class, and Animal class is defined in the same file, python interpreter bypass the error.
In this case, the interpreter recognizes that Animal class defined earlier in the script and will use it as the parent class for the Cow class. However, this is not considered a good practice as it can lead to unexpected behavior if the order of the classes is changed in the script or if the script is imported into another script.
However if you say:
>>> cow = Cow('a', 'b', 'c')
>>> cow.getFamily()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Cow' object has no attribute 'getFamily'

Related

Is there any better way to write this Python code? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 11 months ago.
Improve this question
I am learning to write Object-Oriented Programming in Python and practised the following code. Not sure but I feel that I am writing repetitive code in the inheritance section. Would it be possible to write this code in a better way?
class Dog():
species = "Canis familiaris"
#defining object attributes
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
#INHERITENCE - creating child classes for Breeds
class jackrusselterrier(Dog):
def speak(self,sound="Arf"):
return f"{self.name} says {sound}"
class Dachshund(Dog):
def speak(self,sound="Woof"):
return f"{self.name} says {sound}"
class BullDog(Dog):
def speak(self,sound="Grr"):
return f"{self.name} says {sound}"
#instantiation of object
miles = jackrusselterrier("miles",4)
buddy = Dachshund("buddy",9)
jack = BullDog("Jack",3)
jim = BullDog("Jim",5)
#displaying result
print(miles)
print(miles.speak())
print(type(miles))
print(isinstance(miles,BullDog))
"Better" is a qualitative term, but if you want to repeat less code, there are several ways you could leverage inheritance further to do so (to some extent).
One idea is to make the speak() method in each child class call a shared method from the parent class, _speak(). This has the advantage of better representing that all three child objects have similar underlying behavior.
class Dog():
species = "Canis familiaris"
#defining object attributes
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
def _speak(self,sound):
return f"{self.name} says {sound}"
#INHERITENCE - creating child classes for Breeds
class jackrusselterrier(Dog):
def speak(self,sound="Arf"):
return self._speak(sound)
class Dachshund(Dog):
def speak(self,sound="Woof"):
return self._speak(sound)
class BullDog(Dog):
def speak(self,sound="Grr"):
return self._speak(sound)
#instantiation of object
miles = jackrusselterrier("miles",4)
buddy = Dachshund("buddy",9)
jack = BullDog("Jack",3)
jim = BullDog("Jim",5)
#displaying result
print(miles)
print(miles.speak())
print(type(miles))
print(isinstance(miles,BullDog))
print(buddy.speak())
print(jack.speak())
print(jim.speak())
But each child class still has a method that does pretty much the same thing (calling the parent class), and only differ on their default sound. We could instead only have one speak method, and make this default sound for each class a variable we create when we create the child class. Note however this adds some complexity, as if we make a __init__() method for the child class, we have to call the parent's __init__() method too, and that is a little messy in python.
class Dog():
species = "Canis familiaris"
#defining object attributes
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
def speak(self,sound=None):
if sound is None:
sound = self.default_sound
return f"{self.name} says {sound}"
#INHERITENCE - creating child classes for Breeds
class jackrusselterrier(Dog):
def __init__(self,name,age):
self.default_sound = "Arf"
super(jackrusselterrier,self).__init__(name,age)
class Dachshund(Dog):
def __init__(self,name,age):
self.default_sound = "Woof"
super(Dachshund,self).__init__(name,age)
class BullDog(Dog):
def __init__(self,name,age):
self.default_sound = "Grr"
super(BullDog,self).__init__(name,age)
#instantiation of object
miles = jackrusselterrier("miles",4)
buddy = Dachshund("buddy",9)
jack = BullDog("Jack",3)
jim = BullDog("Jim",5)
#displaying result
print(miles)
print(miles.speak())
print(type(miles))
print(isinstance(miles,BullDog))
print(buddy.speak())
print(jack.speak())
print(jim.speak())
Both these options aren't much less repetitive, but they both have the advantage of communicating in different ways that each child class inherits it's speaking behavior from the parent. Which way you do it I think would come down to your preferred style.

What happens when python imports a class with composition?

Despite of this question being answered:
How to import a class with composition from a module?
I still don't understand the functioning of importing composite classes in python.
The following is a kind of long code but very basic. In a file called example.py there are three classes, Employee, Car and Company. Company calls Employee and employee calls Car.
Employee has a static method which does not work, simply returns a variable that does not exists.
example.py:
class Employee():
def __init__(self,name):
self.name = name
def add_employee_atribute(self):
if ' ' in self.name:
self.completename='created with method class: ^' + self.name.title()
def upperit(self):
return self.name.upper()
#staticmethod
def empstatic(myname):
return myname+myname
#staticmethod
def empstatic_wrong():
# this is wrong
return ERROR
def add_car(self,make):
self.car = Car(make)
class Car():
def __init__(self, make):
self.car = make
class Company():
def __init__(self,name,people):
self.name=name
self.employees=[]
for person in people:
self.employees.append(Employee(person))
def get_all_employess(self):
return 'These are all: ' + ', '.join([e.name for e in self.employees])
def get_employee(self,name):
for e in self.employees:
if e.name == name:
return e
Now if I want to use Company in a file I go:
work.py:
from example import Company
C = Company('kodak',['peter','john smith'])
C.employees[1].add_employee_atribute()
C.get_all_employess()
peter = C.get_employee('peter')
peter.add_car('BMW')
This all works.
Python seems to evaluate the imported code (Company) in work.py in a way that realises that Company needs Employee and Employee needs Car. Very clever. So it looks like python looks for the classes when they are called. Nevertheless python does not realise that the variable 'ERROR' does not exist.
So what puzzles me is the fact that python is able to distinguish, look for the composite classes but not for the variables.
Some explanation about this?

python class question does not give output also error [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
class Vehicle:
def __init__(self, brand, model, type):
self.brand = brand
self.model = model
self.type = type
self.gas_tank_size = 14
self.fuel_level = 0
def fuel_up(self):
self.fuel_level = self.gas_tank_size
print('Gas tank is now full.')
def drive(self):
print(f'The {self.model} is now driving.')
I am a beginner for python class structure so it does not give error but it gives nothing. Could you explain please where is the mistake or what is the problem?
Simply declaring a class does not make anything happen - you have to actually invoke that code outside of the class.
For example, try adding this code below the class, with no indentation (so that python doesn't consider it to be part of the class):
# create an instance of the Vehicle class, and assign it to a variable called 'v'
v = Vehicle("someBrand", "someModel", "someType")
# call the fuel_up() and drive() methods, which should print to the console
v.fuel_up()
v.drive()
A class will not output anything by itself. When make a class object, for example by v = Vehicle(brand, model, type), it will run the __init__ function. This function does not return anything in your code.
If you want it to output anything from any of the other functions of the class, you should continue with something like
v = Vehicle(brand, model, type)
v.fuel_up()
Your code will just create a class and function. It won't do anything until you initialize the class
class Vehicle:
def __init__(self, brand, model, type):
self.brand = brand
self.model = model
self.type = type
self.gas_tank_size = 14
self.fuel_level = 0
def fuel_up(self):
self.fuel_level = self.gas_tank_size
print('Gas tank is now full.')
def drive(self):
print(f'The {self.model} is now driving.')
#Initializing the class
vehicle = Vehicle(brand="Mercedes-Benz", model="A-Class", type="Automatic")
vehicle.fuel_up()
vehicle.drive()
Output:
Gas tank is now full.
The A-Class is now driving.

Python 3.x Beginner: TypeError: dog() takes no arguments

class animal(object):
def __init__(self,name):
self.name = name
def eat(self,food):
print("{} is eating".format(self.name,food))
class dog():
def fetch(self,thing):
print("{} get the {}".format(self.name,thing))
s = dog('r')
error: Traceback (most recent call last): File
"C:\EclipseWorkspaces\csse120\LearnPython\inheritance.py", line 14, in
s = dog('r') TypeError: dog() takes no arguments
Cant figure out whats wrong, please help.
Its a bit late posting an answer, but try adding two underscores per each side of init,
not
_init_
should be
__init__
class animal(object):
def __init__(self,name):
self.name = name
As your error indicates you are trying to create a object of Dog class by passing 'r' parameter to Dog class constructor function. But Dog class does not have a constructor function which accept a char or a string literal as a parameter. It seems like you are trying to use Animal class constructor to create Dog object (Dogs are a subclass of Animal class)
class animal(object):
def __init__(self,name):
self.name = name
To solve this error you should first subclass the Dog class and then create a Dog object.
To subclass Animal class,
class dog(animal):
def fetch(self,thing):
print("{} get the {}".format(self.name,thing))
Now you can use the Animal class constructor and create Dog objects using s = dog('r') statement.
Tip :- I think it is good to use CapWords convention from the beginning for class names as described in the PEP8 styling conventions.
You are missing that dog inherits form animal
class Animal(object):
def __init__(self,name):
self.name = name
def eat(self,food):
print("{} is eating".format(self.name,food))
class Dog(Animal):
def fetch(self,thing):
print("{} get the {}".format(self.name,thing))
s = Dog('r')

Messing around with OOP in Python

I'm playing around with OOP in Python and I am trying to figure out some stuff related to inheritance. . I have some code here that has a few classes. A class called Blacksmith which behaves as expected and a class called Hero which I am trying to call a function from but I recieve an unexpected output.
class Character(object):
def __init__(self,name):
self.health=100
self.name = name
# self.player = player
def printName(self):
print self.name
#def printPlayerName(self):
# print self.player
class Blacksmith(Character):
def __init__(self,name, forgeName):
super(Blacksmith, self).__init__(name)
#self.name = "Billy"
self.forge = Forge(forgeName)
class Hero(Character):
playerName = "Player"
def __init__(self,name):
super(Hero, self).__init__(name)
def setplayername(self,inputplayername):
playerName = inputplayername
class Forge:
def __init__(self,forgeName):
self.name = forgeName
bs = Blacksmith("Billy", "Billy's Forge")
print bs.health
bs.printName()
print bs.forge.name
player1 = Hero("Methos")
print player1.name
player1.setplayername("Chris")
#print playher1.playerName
print player1.playerName
Output is:
raina#DESKTOP-291MTC0 ~/python
$ python learningoopclasses01.py
100
Billy
Billy's Forge
Methos
Player
Can anyone explain why this output says "Player" and not "Chris". Another question I have is I am not entirely sure how the init methods work. What does super do in these cases? What does calling init with a name value do exactly? Thanks.
__init__ is called when an object of that Class is created. With this method, we will also use the self variable to represent the instance of the object itself. It has to be explicitly declared in Python to be defined on an object.
For example,
class Student():
def __init__(self, score1, score2, score3):
self.scores = [score1, score2, score3]
If you want to assign scores to Student 1, you would only need to use because stu_1 already has score as an attribute in it:
stu_1 = Student(80, 90, 85)
In addition, __init__ also will notify you if any parameters are entered incorrectly according to what it has been set up.
super() is used to first call the parent(super) class of Blacksmith, which is Character, and allows you access Character's property.
The call to super() in Blacksmith's __init__ method is equal to its superclass, which in this case is Character.
You could also replace super(Blacksmith, self).__init__(name) with Character.__init__(self, name). The two are equivalent.
A slight adjustment to
def setplayername(self,inputplayername):
self.playerName = inputplayername
In the Hero class will fix it, if you don't want to change anything else.

Categories

Resources