Class object doesn't inherit other class attribute - python-3.x

have 3 classes: Patient, Patients and Hospital.
class Patient:
def __init__(self, ID, name, age, sex, alergies):
self.ID = ID
self.name = name
self.age = age
self.sex = sex
self.alergies = alergies
def Is_old(self):
if self.age >= 60:
return True
else:
return False
def Add_patient(self, P):
pass
class Patients():
def __init__(self):
self.dict = {} # where key is a patient ID, value is an Patient object
class Hospital(Patients):
def __init__(self, name):
self.name = name
def Get_oldPatients(self):
old_patients = []
for key, value in self.dict.items(): # where an error appears
if Patient.Is_old():
old_patients.append(value)
return old_patients
an error appears
AttributeError: 'Hospital' object has no attribute 'dict'
Hospital class inherit from Patients so should have the same attribs like Patients, any idea where is the problem?

Related

Attribute Error in python, object has no attribute

I am new to inheritance in classes and for some reason, the attributes in this code don't seem to be sharing correctly. I'm not sure what the issue is.
class Person:
def __init__(self, name, age, occupation):
self.name = name
self.age = age
self.occupation = occupation
def say_hello(self):
print(f"Hello, my name is {self.name}.")
def say_age(self):
print(f"I am {self.age} years old.")
class Superhero(Person):
def __init__(self, name, age, occupation, secret_identity, nemesis):
self.secret_identity = secret_identity
self.nemesis = nemesis
hero = Superhero("Spider-Man", 17, "student", "Peter Parker", "Green Goblin")
print(hero.name())
It looks like you're not calling the super constructor in your Superhero class.
You should do as follow:
class Superhero(Person):
def __init__(self, name, age, occupation, secret_identity, nemesis):
super().__init__(name, age, occupation)
self.secret_identity = secret_identity
self.nemesis = nemesis
BTW: you didn't define a function named name. If you want to print the name you should remove the (), e.g print(hero.name)

Python: for multiple properties use one getter and setter method

I have created a class that has multiple properties. I want to use one function for the getter method and the second one for the setter method.
class person:
def __init__(self, fname, lname, city, state):
# make all attributes as private
self._fname = fname
self._lname = lname
self._city = city
self._state = state
#property # get method
def fname(self):
return self._fname
#fname.setter # set method
def fname(self,fname):
self._fname = fname
#property
def lname(self):
return self._lname
#lname.setter
def lname(self,lname):
self._lname = lname
#property
def city(self):
return self._city
#city.setter
def city(self, city):
self._city = city
#property
def state(self):
return self._state
#state.setter
def state(self, state):
self._state = state
How to use all properties for one get methods and one set method?
e.g.:
def get(self):
return self._attr
def set(self,value):
self._attr = value
class person:
def __set_name__(self, name):
self.name = name
def __get__(self, obj, type=None) -> object:
return obj.__dict__.get(self.name)
def __set__(self, obj, value) -> None:
obj.__dict__[self.name] = value
my_value = person
my_values.fname = 'Shivam'
my_values.lname = 'Gupta'
print(my_values.fname) #--> Shivam
print(my_values.lname) #--> Gupta

Implementing a python class

I am working on a personal project and I am having trouble implementing this following part.
Implementing a Menu Class.
This class will make use of MenuItem objects.
This class represents the restaurant menu which contains 4 different categories of menu item diners can order from.
This class will have a single class(or static) variable:
Menu_Item_types: a list containing 4 strings representing the 4 possible types of menu items.: Drink, appetizer, entree, dessert.
This class will use the following instance attribute:
List item
self.menuItemDrinkList: list of all drink list
self.menuItemAppetizerList: list of all appetizer list
self.menuItemEntreeList: a list of all entree list
self.menuItemDessertList: a list of all the dessert list
Below is the menuItem object
class MenuItem:
def __init__(self, name=None, types=None, price=None, description=None):
self.name = name
self.types = types
self.price = price
self.description = description
def setName(self, name):
self.name = name
def getName(self):
return self.name
def setTypes(self, types):
self.types = types
def getTypes(self):
return self.types
def setPrice(self, price):
self.price = price
def getPrice(self):
return self.price
def setDescription(self, description):
self.description = description
def getDescription(self):
return self.description
def __str__(self):
return "{} ({}): ${}, {}".format(self.name, self.types, self.price, self.description)
If I understand you correctly you are looking for setters and getters properties. Here is the way how you do it in Python.
You can learn more about properties here:
class MenuItem:
def __init__(self, name=None, types=None, price=None, description=None):
self._name = name
self._types = types
self._price = price
self._description = description
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
#property
def types(self):
return self._types
#types.setter
def types(self, types):
self._types = types
#property
def price(self):
return self._price
#price.setter
def price(self, price):
self._price = price
#property
def description(self):
return self._description
#description.setter
def description(self, description):
self._description = description
def __str__(self):
return "{} ({}): ${}, {}".format(
self._name, self._types, self._price, self._description
)
menu_item = MenuItem("pizza", "entry", 10)
print(menu_item)
menu_item.price = 20
menu_item.description = "Delicious"
print(menu_item)
output:
pizza (entry): $10, None
pizza (entry): $20, Delicious
Please notice:
In python you don't call properties with getXxx or setXxx, you just use regular names and decoreate methods with #property and #xxx.setter
You should have #property before #setter.
Setter must start with the property name
In order to escape recursion, name your internal
attributes with _ (_name). If you will not do it you will have a
"RecursionError: maximum recursion depth exceeded in comparison"
because setter will call itself in the loop.

How can I return all values inside of a class variable?

I'm writing a text adventure game in Python and I'm curious on how I can go about listing all the items inside of the Room class
I'm very new to Python and have very limited practice.
# Declaring items and assigning them rooms
dingus = Item("Dingus", "This really dings.")
room["garden"].add_item(dingus)
flippers = Item("Flippers", "Webbed in nature.")
room["garden"].add_item(flippers)
# Declare all the rooms
room = {
'garden': Room("Garden",
"""The flowers are blooming wonderfully. To the south lies a dark path.""")
}
class Room:
def __init__(self, title, description):
self.title = title
self.description = description
self.items = []
self.items_in_room = ''
def __repr__(self):
print(f"-" * 40)
return (f"You are at the {self.title}.")
def add_item(self, item):
return self.items.append(item)
def list_items_in_room(self):
for item in self.items:
self.items_in_room += item
', '.split(self.items)
return self.items
class Item:
def __init__(self, name, description):
self.name = name
self.description = description
def __str__(self):
return f'{self.name} - {self.description}' + '\n' + "-" * 40
I'm expecting Room.list_items_in_room to list all the items in the room in a comma separated string.
I have re-arranged your code and also changed the function list_items_in_room. Also, have changed the __str__ function to __repr__ and removed the '-' * 40 (I couldn't understand why that's there).
class Room:
def __init__(self, title, description):
self.title = title
self.description = description
self.__items = []
# __ so that it's not modifiable without getter and setter functions
def __repr__(self):
print(f"-" * 40)
return (f"You are at the {self.title}.")
def add_item(self, item):
return self.__items.append(item)
def list_items_in_room(self):
return self.__items
class Item:
def __init__(self, name, description):
self.name = name
self.description = description
def __repr__(self):
return f'{self.name} - {self.description}'
# Declare all the rooms
room = {
'garden': Room("Garden",
"""The flowers are blooming wonderfully. To the south lies a dark path.""")
}
dingus = Item("Dingus", "This really dings.")
room["garden"].add_item(dingus)
flippers = Item("Flippers", "Webbed in nature.")
room["garden"].add_item(flippers)
print(room['garden'].list_items_in_room())
Output:
[Dingus - This really dings., Flippers - Webbed in nature.]

Why do i get a type error when using super()?

I just started learning about classes and inheritance in Python 3. I want to print the name of a student, which is inherited from the superclass Person. Unfortunately I keep getting a TypError.
code:
class Person(object):
def __init__(self, name="Mike", age = 25, place_of_birth="Stockholm"):
self.age = age
self.name = name
self.place_of_birth = place_of_birth
class Student(Person):
def __init__(self, name, age, university = "University of Stockholm", gpa = 8):
super().__init__(name, age)
self.university = university
self.gpa = gpa
I then like to print the name of the student by calling:
student1 = Student()
print(student1.name)
But I keep getting this error message:
Traceback (most recent call last):
TypeError: init() missing 2 required positional arguments: 'name' and 'age'
If you want Student to always default to the name and age of the Parent class then you don't want Student to take a name and age value.
class Student(Person):
def __init__(self, university = "University of Stockholm", gpa = 8):
super().__init__() # runs parent __init__ taking no values
self.university = university
self.gpa = gpa
>>> student1 = Student()
>>> student1.name
'Mike'
>>> student1.age
25
When you use super().__init__(name, age) you are wanting to pass the name and age given to the Student class to the Parent class. But since you don't want to pass anything it is getting errors.
Now, if you want the Student class to be able to take values as well as default to the ones provided by the parent class you can do this.
class Student(Person):
def __init__(self, name = None, age = None, university = "University of Stockholm", gpa = 8):
if name is None and age is None:
super().__init__()
else:
super().__init__(name, age)
self.university = university
self.gpa = gpa
What happens here is if no name or age is provided if name is None and age is None then it defaults to the values from Person class. However if both the name and age are provided, then it will use those values.
>>> student1 = Student()
>>> student1.name
'Mike'
>>> student1.age
25
>>> student2 = Student('Bill', 19)
>>> student2.name
'Bill'
>>> student2.age
19
The __init__() method of Student takes 2 positional arguments: name and age. You need to specify those arguments when creating a new instance:
student1 = Student('eppe2000', 20)
print(student1.name)
If you instead want the class Student to default to class Person default arguments, in case they have not been specified, you can do it like this:
class Person(object):
def __init__(self, name="Mike", age=25, place_of_birth="Stockholm"):
self.age = age
self.name = name
self.place_of_birth = place_of_birth
class Student(Person):
def __init__(self, university="University of Stockholm", gpa=8, **kwargs):
super().__init__(**kwargs)
self.university = university
self.gpa = gpa
>>> s = Student()
>>> s.name
'Mike'
>>> s = Student(name="Daniele")
>>> s.name
'Daniele'
Basically you forward all the keywords arguments that are unknown to the class Student to its parent class. Not that if you specify an invalid keyword (i.e: 'surname') you will get a TypeError because neither Student or Person specify a keyword argument with key 'surname'.
If you need info about **kwargs check this post: https://stackoverflow.com/a/36908/3477005

Resources