class Property:
def __init__(self, square_feet='', beds='',
baths='', **kwargs):
super().__init__(**kwargs)
self.square_feet = square_feet
self.num_bedrooms = beds
self.num_baths = baths
def display(self):
print("PROPERTY DETAILS")
print("================")
print("square footage: {}".format(self.square_feet))
print("bedrooms: {}".format(self.num_bedrooms))
print("bathrooms: {}".format(self.num_baths))
print()
@staticmethod
def prompt_init():
return dict(square_feet=input("Enter the square feet: "),
beds=input("Enter number of bedrooms: "),
baths=input("Enter number of baths:"))
class Apartment(Property):
valid_laundries = ("coin", "ensuite", "none")
valid_balconies = ("yes", "no", "solarium")
def __init__(self, balcony='', laundry='', **kwargs):
super().__init__(**kwargs)
self.balcony = balcony
self.laundry = laundry
def display(self):
super().display()
print("APARTMENT DETAILS")
print("laundry: %s" % self.laundry)
print("has balcony: %s" % self.balcony)
@staticmethod
def prompt_init():
parent_init = Property.prompt_init()
laundry = get_valid_input('What laundry facilities does '
'the property have? ', Apartment.valid_laundries)
while laundry.lower() not in \
Apartment.valid_laundries:
laundry = input("What laundry facilities does "
"the property have? ({})".format(
", ".join(Apartment.valid_laundries)))
balcony = ''
while balcony.lower() not in \
Apartment.valid_balconies:
balcony = input(
"Does the property have a balcony? "
"({})".format(
", ".join(Apartment.valid_balconies)))
parent_init.update({
"laundry": laundry,
"balcony": balcony
})
return parent_init
class House(Property):
valid_garage = ("attached", "detached", "none")
valid_fenced = ("yes", "no")
def __init__(self, num_stories='',
garage='', fenced='', **kwargs):
super().__init__(**kwargs)
self.garage = garage
self.fenced = fenced
self.num_stories = num_stories
def display(self):
super().display()
print("HOUSE DETAILS")
print("# of stories: {}".format(self.num_stories))
print("garage: {}".format(self.garage))
print("fenced yard: {}".format(self.fenced))
@staticmethod
def prompt_init():
parent_init = Property.prompt_init()
fenced = get_valid_input("Is the yard fenced? ",
House.valid_fenced)
garage = get_valid_input("Is there a garage? ",
House.valid_garage)
num_stories = input("How many stories? ")
parent_init.update({
"fenced": fenced,
"garage": garage,
"num_stories": num_stories
})
return parent_init
def get_valid_input(input_string, valid_options):
input_string += " ({}) ".format(", ".join(valid_options))
response = input(input_string)
while response.lower() not in valid_options:
response = input(input_string)
return response
class Purchase:
def __init__(self, price='', taxes='', **kwargs):
super().__init__(**kwargs)
self.price = price
self.taxes = taxes
def display(self):
super().display()
print("PURCHASE DETAILS")
print("selling price: {}".format(self.price))
print("estimated taxes: {}".format(self.taxes))
@staticmethod
def prompt_init():
return dict(
price=input("What is the selling price? "),
taxes=input("What are the estimated taxes? "))
class Rental:
def __init__(self, furnished='', utilities='',
rent='', **kwargs):
super().__init__(**kwargs)
self.furnished = furnished
self.rent = rent
self.utilities = utilities
def display(self):
super().display()
print("RENTAL DETAILS")
print("rent: {}".format(self.rent))
print("estimated utilities: {}".format(
self.utilities))
print("furnished: {}".format(self.furnished))
@staticmethod
def prompt_init():
return dict(
rent=input("What is the monthly rent? "),
utilities=input(
"What are the estimated utilities? "),
furnished = get_valid_input(
"Is the property furnished? ",
("yes", "no")))
class HouseRental(Rental, House):
@staticmethod
def prompt_init():
init = House.prompt_init()
init.update(Rental.prompt_init())
return init
init = HouseRental.prompt_init()
print(init)
house = HouseRental(**init) #I assume this holds the input from all the prompt_init, from class Property to class Rental.
house.display()
My question is how super interacts with a class with no parent class. In the last line, house.display() is called and class HouseRental inherits 2 classes, the first which has no parent class. I see that when house.display() is called, it calls Rental.display() first, then the super() call in Rental.display() does not raise an error, but points to the next inherited class, House.display(), which then the super() call in House.display() points to its parent class, Property.
I get the gist of how super() works in this kind of way but I don't fully understand why super() in a base class points to the next class in the MRO instead of raising an error (something like "no parent class available")
Here is the output of house.display if you're interested:
{'square_feet': '1', 'beds': '2', 'baths': '3', 'fenced': 'no', 'garage': 'none', 'num_stories': '3', 'rent': '1', 'utilities': '4', 'furnished': 'no'}
PROPERTY DETAILS
================
square footage: 1
bedrooms: 2
bathrooms: 3
HOUSE DETAILS
# of stories: 3
garage: none
fenced yard: no
RENTAL DETAILS
rent: 1
estimated utilities: 4
furnished: no