0
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
Steve Hemmingsen
  • 383
  • 5
  • 19

1 Answers1

0

All classes in Python implicitly inherit from the Object type: Python class inherits object.

Calling super().__init__ in a class with "no super class" will simply call the constructor for Object.

Sara M
  • 455
  • 3
  • 7
  • Oh I completely forgot about that. So if I'm understanding this correctly, it calls "object", which points to the next "object" in the MRO which is House? (context: `class HouseRental(Rental, House)`) – Steve Hemmingsen Dec 07 '17 at 06:45
  • It would be helpful if you could create a smaller more specific example to reduce the scope of the question's domain. – Sara M Dec 07 '17 at 06:51