There is super class with the name Employee has the following fields.
empNum, name, address and DOB.
There are two child class or sub class of Employee class. They are FullTimeEmployee and PartTimeEmployee.
FullTimeEmployee has monthlySalary (other than the fields in Super Class)
PartiTime Employee has hourlyRate (other than the fields in Super Class)
Here is a code that i have written in Python.
However when i print it is only printing the fields in the superclass.
May i know which part im doing wrong.
class Employee:
def __init__(self, **kwargs):
if 'empNum' in kwargs:self._empNum=kwargs['empNum']
if 'name' in kwargs:self._name=kwargs['name']
if 'address' in kwargs:self._address=kwargs['address']
if 'dob' in kwargs:self._dob=kwargs['dob']
def empNum(self,en=None):
if en:self._empNum=en
return self._empNum
def name(self,nme=None):
if nme:self._name=nme
return self._name
def address(self,addr=None):
if addr:self._address=addr
return self._address
def dob(self,db=None):
if db:self._dob=db
return self._name
def __str__(self):
return self._empNum +","+ self._name+","+self._dob+","+self._address
#child class
class FullTimeEmployee(Employee):
def __init__(self, **kwargs):
super().__init__( **kwargs)
if 'monthlySalary' in kwargs:self._monthlySalary=kwargs['monthlySalary']
def monthlySalary(self, s=None):
if s:self._monthlySalary=s
return self._monthlySalary
def _str_(self):
return super().__init__ + "," + self._monthlySalary
#child class
class PartTimeEmployee(Employee):
def __init__(self, **kwargs):
super().__init__( **kwargs)
if 'hourlyRate' in kwargs:self._hourlyRate=kwargs['hourlyRate']
def hourlyRate(self, hr=None):
if hr:self._hourlyRate=hr
return self._hourlyRate
def _str_(self):
return str(super()._str_()) +"," + self._hourlyRate
def main():
records = []
test = []
emp = Employee(empNum='100', name="Ibrahim Shathir", address="H. North Pole,Male', Maldives", dob="16-05-1989")
records.append(emp)
emp1 = PartTimeEmployee(empNum='101', name="Mohamed Latheef", address="H. North Pole,Male', Maldives", dob="16-05-1989", hourlyRate="150")
records.append(emp1)
emp2 = FullTimeEmployee(empNum='102', name="Shujau Ibrahim", address="H. North Pole,Male', Maldives", dob="16-05-1989", monthlySalary="12500")
records.append(emp2)
print(records[0])
for emps in records:
print(emps)
print(emp2)
if __name__ == '__main__':main()
[1]: https://i.stack.imgur.com/7pzph.jpg
[2]: https://i.stack.imgur.com/JbOHv.jpg
Please override __str__ instead of _str_ in subclass. The following code should work.
class Employee:
def __init__(self, **kwargs):
if 'empNum' in kwargs:self._empNum=kwargs['empNum']
if 'name' in kwargs:self._name=kwargs['name']
if 'address' in kwargs:self._address=kwargs['address']
if 'dob' in kwargs:self._dob=kwargs['dob']
def empNum(self,en=None):
if en:self._empNum=en
return self._empNum
def name(self,nme=None):
if nme:self._name=nme
return self._name
def address(self,addr=None):
if addr:self._address=addr
return self._address
def dob(self,db=None):
if db:self._dob=db
return self._name
def __str__(self):
return self._empNum +","+ self._name+","+self._dob+","+self._address
#child class
class FullTimeEmployee(Employee):
def __init__(self, **kwargs):
super().__init__( **kwargs)
if 'monthlySalary' in kwargs:self._monthlySalary=kwargs['monthlySalary']
def monthlySalary(self, s=None):
if s:self._monthlySalary=s
return self._monthlySalary
def __str__(self):
prefix = super().__str__()
return '{}, {}'.format(prefix, self._monthlySalary)
#child class
class PartTimeEmployee(Employee):
def __init__(self, **kwargs):
super().__init__( **kwargs)
if 'hourlyRate' in kwargs:self._hourlyRate=kwargs['hourlyRate']
def hourlyRate(self, hr=None):
if hr:self._hourlyRate=hr
return self._hourlyRate
def __str__(self):
prefix = super().__str__()
return '{}, {}'.format(prefix, self._hourlyRate)
def main():
records = []
test = []
emp = Employee(empNum='100', name="Ibrahim Shathir", address="H. North Pole,Male', Maldives", dob="16-05-1989")
records.append(emp)
emp1 = PartTimeEmployee(empNum='101', name="Mohamed Latheef", address="H. North Pole,Male', Maldives", dob="16-05-1989", hourlyRate="150")
records.append(emp1)
emp2 = FullTimeEmployee(empNum='102', name="Shujau Ibrahim", address="H. North Pole,Male', Maldives", dob="16-05-1989", monthlySalary="12500")
records.append(emp2)
print(records[0])
for emps in records:
print(emps)
print(emp2)
if __name__ == '__main__':main()
Related
I want to separate the DB models from the actual classes. But i need two static functions for fetching data from the DB regardless of the subclass type. the implementation for both functions are the same across all DB models.
pyright showing an error that cls inside get() and get_all() functions doesn't have a db property.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name):
self.name = name
#abstractstaticmethod
def save(m):
pass
#abstractstaticmethod
def _from_model(obj):
pass
#classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
#classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class DogSound:
def __init__(self, name):
self.name = name
def sound(self):
print(self.name, ": DOG SOUND!!")
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super(Dog, self).__init__(name)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
Dog.get(1).sound()
I cannot duplicate your first error.
Your second issue is a result of method sound implicitly returning None since it has no return statement and you have print(Dog.get(1).sound()), which will print out the return value from that method. You either want to change this to just Dog.get(1).sound() or modify the sound method to return what it is currently being printed and remove the print statement (my choice).
As an aside, I found this class structure a bit difficult to follow. Why do you need a separate DogSound class with a name attribute which should belong to Animal? Also, it seems to me that age could/should be an attribute of Animal since both cats and dogs have an age.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name, age):
self.name = name
self.age = age
#abstractstaticmethod
def save(m):
pass
#abstractstaticmethod
def _from_model(obj):
pass
#classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
#classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class Dog(Animal):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
def sound(self):
return f"{self.name}: DOG SOUND!!"
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name, age)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
print(Dog.get(1).sound())
Prints:
CAT2
DOG2
[CAT1, CAT2, CAT3]
[DOG1, DOG2, DOG3]
DOG2: DOG SOUND!!
If for some reason you want DogSound to be a separate class, then there is no need for the name attribute to be duplicated:
...
class DogSound: # A "Mixin" class
def sound(self):
return f"{self.name}: DOG SOUND!!"
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
...
Every time I run my code it pops up the message saying "'ICU' object has no attribute '_name'. Did you mean: 'name'?" I can not figure out how to fix it. I've tried changing the name of the accessors and mutators but still can't figure out how to solve it. Any suggestions?
Here's my code:
class Patient:
def __init__(self, name, age):
self.name = name
self.age = age
self.weight = 150
#property
def age(self):
return self._age
#age.setter
def age(self, newValue):
if newValue > 0:
self._age = newValue
else:
self._age = 0
#property
def weight(self):
return self._weight
#weight.setter
def weight(self, newValue):
if newValue >=0 and newValue <= 1400:
self._weight = newValue
#IncreaseAge
def increaseAge(self):
self.age = self.age + 1
class In(Patient):
def __init__(self, name, age, stay):
self.name = name
self.age = age
self.stay = stay
#property
def stay(self):
return self._stay
#stay.setter
def stay(self, value):
self._name = value
def __str__(self):
print("IN-" + self._name + self._age + self.weight + self._stay)
class Out(Patient):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
print("OUT-" + self._name + self._age + self._weight)
class ICU(In):
def __init__(self, name, age):
self.name = name
self.age = age
self.days = 5
class CheckUp(Out):
def __init__(self, name, age):
self.name = name
self.age = age
Here's the rest of the instance:
# Create three patient objects and print them out
p1 = ICU("Ben Dover", 0)
p2 = ICU("Helen Hywater", -15)
p3 = CheckUp("Amanda Lynn", 45)
p4 = ICU("Chester Minit", 12)
p5 = In("Don Keigh", 89, 10)
p6 = Out("Kay Oss ", 45)
print ("\tStatus\tName\t\tAge\tWeight\tStay")
print ("-" * 55)
print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))
print ("-" * 55)
# Change their ages and print them out
p1.age = -5
p2.age = 100
for i in range(6):
p3.increaseAge()
p4.age = 0
p5.increaseAge()
p6.age = 42
print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))
print ("-" * 55)
# Change other instance variables and print them out
p1.weight = 2000
p1.stay = 3
p2.name = "Justin Thyme"
p2.weight = 220
p2.stay = 0
p3.weight = -50
p4.weight = 1400
p5.weight = 0
p5.stay = 21
p6.weight = 1401
print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))
print ("-" * 55)
It's because your variable name is different.
Replace you code from:
#stay.setter
def stay(self, value):
self._name = value
To:
#stay.setter
def stay(self, value):
self.name = value
In Python, constructors - like all other methods - can be overridden. That is once you define __init__ in child classes, the base class method is never called. This is what's causing the error.
You need to explicitly call the base class like like this:
class ICU(In):
def __init__(self, name, age):
self.name = name
self.age = age
self.days = 5
In.__init__(self, name, age, 10) # stay = 10 since it's not an input parameter in the ICU __init__ method.
This needs to be done in every base class. So you'd do something similar in the In class as well.
The problem comme to the fact that "format" is calling "__ str__" on your instances but when "__ str__" get called, some of your instance doesn't have a value for "_name" or "_stay" or "_weight"...see your " __ init __ " method for each instance and execute " __ str __" after you will see the problem. so to handle this case you have the following simple solution
class In(Patient):
def __init__(self, name, age, stay):
self.name = name
self.age = age
self.stay = stay
#property
def stay(self):
return self._stay
#stay.setter
def stay(self, value):
self._name = value
def __str__(self):
x = (
getattr(self, '_name', ''),
getattr(self, '_age', ''),
self.weight or ''
getattr(self, '_stay', ''),
)
return ("IN-%s %s %s %s")%(*x)
class Out(Patient):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
x = (
getattr(self, '_name', ''),
getattr(self, '_age', ''),
getattr(self, '_stay', ''),
)
return "OUT- %s %s %s"%(*x)
But your classes are not well designed, see below something interesting
class Patient:
def __init__(self, name, age, weight=150):
self._name= name
self._age = age
self._weight = weight
#property
def name(self):
return self._name
#name.setter
def name(self, value):
assert isinstance(value, str)
self._name = value
#property
def age(self):
return self._age
#age.setter
def age(self, value):
assert isinstance(value, int)
self._age = value
#property
def weight(self):
return self._weight
#weight.setter
def weight(self, value):
assert isinstance(value, int)
self._weight = value
def __str__(self):
return f"{self.__class__.__name__.upper()}-{self.name} {self.age} {self.weight}"
class Out(Patient):
pass
class In(Patient):
def __init__(self, name, age, stay, weight=150):
super().__init__(name, age, weight=weight)
self._stay = stay
#property
def stay(self):
return self._stay
#stay.setter
def stay(self, value):
assert isinstance(value, int)
self._stay = value
def __str__(self):
return f"{super().__str__()} {self.stay}"
class ICU(In):
def __init__(self, name, age):
super().__init__(name, age, 5)
class CheckUp(Out):
def __init__(self, name, age):
super().__init__(name, age)
Also note that "increaseAge" method is not defined on your instances
I have my class.
I want to create a method inside to delete a list item by code attribute.
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
print("The code: {self.__code} was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
print(list)
lista.deleteitem(123)
How I can create a method who deletes the code that I send?
Regards
You can try this below :
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
# Logic for deletion
for obj in list:
if obj.code == code:
list.remove(obj)
print("The code: "+code+" was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
myclass = MyClass(None, None)
myclass.__deleteitem__(123)
In the Person object, there is already a support for an inventory, and when the Person object takes a Weapon object or Food object, the object would go to the inventory. For the Tribute object, I want to retrieve the Weapon objects from the inventory by creating a new method in the Tribute class, get_weapons(), which would return a tuple of Weapon objects that the Tribute currently has in his inventory.
class Tribute(Person):
...
def get_weapons(self):
self.weapons=[]
for item in self.get_inventory():
if isinstance(item,Weapon):
self.weapons.append(item)
return tuple(self.weapons)
cc = Tribute("Chee Chin", 100)
chicken = Food("chicken", 5)
aloe_vera = Medicine("aloe vera", 2, 5)
bow = RangedWeapon("bow", 4, 10)
sword = Weapon("sword", 2, 5)
Base = Place("base")
Base.add_object(cc)
Base.add_object(chicken)
Base.add_object(aloe_vera)
Base.add_object(bow)
Base.add_object(sword)
cc.take(bow) # Chee Chin took bow
cc.take(sword) # Chee Chin took sword
cc.take(chicken) # Chee Chin took chicken
cc.take(aloe_vera) # Chee Chin took aloe_vera
But I keep getting AttributeError: 'RangedWeapon' object has no attribute 'owner'. I'm not sure what went wrong. I would really appreciate some help. Thank you!
import random
from collections import OrderedDict
######################
# Class: NamedObject #
######################
class NamedObject(object):
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
#######################
# Class: MobileObject #
#######################
class MobileObject(NamedObject):
def __init__(self, name, place):
super().__init__(name)
self.place = place
def get_place(self):
return self.place
################
# Class: Thing #
################
class Thing(MobileObject):
def __init__(self, name):
super().__init__(name, None)
self.owner = None
def set_owner(self, owner):
self.owner = owner
def get_owner(self):
return self.owner
def is_owned(self):
return self.owner is not None
#################
# Class: Person #
#################
class Person(LivingThing):
def __init__(self, name, health, threshold):
self.inventory = []
super().__init__(name, health, threshold)
def take(self, thing):
# Can only take things in current location and not owned by others
if isinstance(thing, Thing) and thing in self.place.objects and not thing.is_owned():
thing.set_owner(self)
self.inventory.append(thing)
self.place.del_object(thing)
GAME_LOGGER.add_event("TOOK", self, thing)
else:
GAME_LOGGER.warning("{} cannot take {}.".format(self.get_name(), thing.get_name()))
def remove_item(self, thing):
#Can only remove things in inventory
if isinstance(thing, Thing) and thing in self.get_inventory() and thing.get_owner()==self:
thing.set_owner(None)
self.inventory.remove(thing)
else:
GAME_LOGGER.warning("{} does not own {}.".format(self.get_name(), thing.get_name()))
def go(self, direction):
new_place = self.place.get_neighbor_at(direction.upper())
if new_place is not None:
self.move_to(new_place)
else:
GAME_LOGGER.warning("{} cannot go {} from {}".format(self.get_name(), direction, self.get_place().get_name()))
def get_inventory(self):
return list(self.inventory)
def objects_around(self):
return list(filter(lambda t: t is not self, self.get_place().get_objects()))
def get_exits(self):
return self.get_place().get_exits()`
class Weapon(Thing):
def __init__(self, name, min_dmg, max_dmg):
self.name=name
self.min_dmg=min_dmg
self.max_dmg=max_dmg
def min_damage(self):
return self.min_dmg
def max_damage(self):
return self.max_dmg
def damage(self):
return random.randint(self.min_dmg,self.max_dmg)
class RangedWeapon(Weapon):
def __init__(self, name, min_dmg, max_dmg):
super().__init__(name, min_dmg, max_dmg)
self.shots=0
def shots_left(self):
return self.shots
def load(self, ammo):
if ammo.weapon_type()==self.name:
self.shots+=ammo.get_quantity()
ammo.remove_all()
def damage(self):
if self.shots==0:
return 0
else:
self.shots-=1
return super().damage()
not an expert on python 3.x, but:
class Weapon(Thing):
def __init__(self, name, min_dmg, max_dmg):
self.name=name
self.min_dmg=min_dmg
self.max_dmg=max_dmg
you never actually set Weapon to inherit from Thing - you need to call the super().__init__ line that's appropriate for Thing, in Weapon's ctor. its an annoying python quirk.
have a look here - at RangedWeapon's ctor - you're doing it right:
super().__init__(name, min_dmg, max_dmg)
My simplified code is below: it creates an animal, and places it inside a zoo. I want to print the list of animals within the zoo. Going round in circles with this!
class Animal(object):
def __init__(self, name):
self.name = name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
rep = ", ".join(self.animals)
return rep
def add(self, name):
self.animals.append(Animal(name))
def main():
while True:
zoo = Zoo()
animal = input("add an animal: ")
zoo.add(animal)
print(zoo)
main()
The added __repr__ Method to the Animal returns us the name.
The zoo = Zoo() has to be outside of the loop, this makes sure that we do not create a new zoo with every iteration.
Then we print the list (zoo.animals).
class Animal(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
rep = ", ".join(self.animals)
return rep
def add(self, name):
self.animals.append(Animal(name))
def main():
zoo = Zoo()
while True:
animal = input("add an animal: ")
zoo.add(animal)
print(zoo.animals)
main()
You can simply refer to the name property of Animal in your Zoo.__str__(), e.g.:
def __str__(self):
return ', '.join(animal.name for animal in self.animals)
Now print(zoo) should work correctly.
However this doesn't provide a lot of encapsulation if say you wanted to change what it means to print an animal, e.g. height, size, etc. So perhaps a more encapsulated form would be:
class Animal(object):
...
def __str__(self):
return self.name
class Zoo(object):
...
def __str__(self):
return ", ".join(str(animal) for animal in self.animals)
Now when you print(zoo) the Animal class is responsible for its own string presentation.
Just as a note: you probably should create the Animal instance outside of Zoo, what happens if you decide to create a class hierarchy of Animals (e.g. Mammal) that has different behaviours, your Zoo class would only know about Animals.
class Animal(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Zoo(object):
def __init__(self):
self.animals = []
def __str__(self):
return ", ".join(str(animal) for animal in self.animals)
def add(self, animal):
self.animals.append(animal)
def main():
zoo = Zoo()
while True:
animal = Animal(input("add an animal: "))
zoo.add(animal)
print(zoo)
main()
This would still behave properly if you create a Mammal class:
class Mammal(Animal):
...
zoo.add(Mammal(...))
print(zoo)