Reputation: 81
I'm following book about object oriented Python and I stumbled upon code that quite doesn't make sense to me:
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(f'square footage: {self.square_feet}')
print(f'bedrooms: {self.num_bedrooms}')
print(f'bathrooms: {self.baths}')
print()
def prompt_init():
return dict(square_feet=input('Enter the square feet: '),
beds=input('bedrooms: '), baths=input('baths: '))
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
prompt_init = staticmethod(prompt_init)
then I have:
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(f'# of stories: {self.num_stories}')
print(f'garage: {self.garage}')
print(f'fenced yard: {self.fenced}')
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
prompt_init = staticmethod(prompt_init)
class Rental:
def __init__(self, furnished='', utilities='', rent='', **kwargs):
super().__init__(**kwargs)
self.furnished = furnished
self.utilities = utilities
self.rent = rent
def display(self):
super().display()
print('RENTAL DETAILS')
print(f'rent: {self.rent}')
print(f'estimated utilities: {self.utilities}')
print(f'furnished: {self.furnished}')
def prompt_init():
return dict(
rent=input('What is the monthly rent ? '), utilities=input('What are the estimated utilities ? '),
furnished=input('Is the property furnished ? ', ('yes', 'no')))
prompt_init = staticmethod(prompt_init)
class HouseRental(Rental, House):
def prompt_init():
init = House.prompt_init()
init.update(Rental.prompt_init())
return init
prompt_init = staticmethod(prompt_ini
when I instantiate HouseRental
class like this:
init = HouseRental.prompt_init()
I'm getting bunch of prompts as expected but I'm also getting error
get_valid_input not defined
on the line I marked with -->
, Which doesn't make sense to me because the method is defined in Property
superclass and House
class is a subclass of Property
which inherits all methods Property
have.
How come House
class isn't recognizing the method?
Upvotes: 3
Views: 92
Reputation: 12918
Pass self
as the first argument to your prompt_init
method in House
, and call the inherited method with self.get_valid_inputs(...)
.
In your House
class:
def prompt_init(self):
parent_init = Property.prompt_init()
fenced = self.get_valid_input('Is the yard fenced ? ', House.valid_fenced)
garage = self.get_valid_input('Is there a garage ? ', House.valid_garage)
num_stories = input('How many stories ? ')
# ...
You also have to pass self
as the first argument of the parent class's get_valid_input
method. This is because Python automatically passes a reference to the calling object as the first argument to class methods, so if you do not account for that in your signature, you will get "too many arguments" errors.
In your Property
class:
def get_valid_input(self, input_string, valid_options):
input_string += ' ({}) '.format(', '.join(valid_options))
response = input(input_string)
# ...
Then house = House().prompt_init()
ran without errors for me.
It looks like you might need to add self
as an argument to all of your other prompt_init
methods for your subclasses. Generally you should always pass self
as the first argument to methods in a class.
Upvotes: 1
Reputation: 81
What worked for me was pulling the method out of the superclass and leaving it in global scope like this:
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 Property:
...
# other methods
...
class House(Property):
...
# other methods
...
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
class HouseRental(Rental, House):
def prompt_init():
init = House.prompt_init()
init.update(Rental.prompt_init())
return init
prompt_init = staticmethod(prompt_init)
Upvotes: 0