Chapter 9

Author

Shah Nawaz

9-1. Restaurant:

Make a class called Restaurant. The init() method for Restaurant should store two attributes: a restaurant_name and a cuisine_type. Make a method called describe_restaurant() that prints these two pieces of information, and a method called open_restaurant() that prints a message indi- cating that the restaurant is open. Make an instance called restaurant from your class. Print the two attri- butes individually, and then call both methods.

class Restaurant:

    def __init__(self,name,cuisine_type):
        self.restaurant_name = name.title()
        self.cuisine = cuisine_type.title()

    def describe_restaurant(self):
        print(f"Name of restaurant is {self.restaurant_name}")
        print(f"Type of cuisine in restaurant is {self.cuisine}")

    def open_restaurant(self):
        print(f"{self.restaurant_name} is open")

    
recipes = Restaurant("shangrilla","Salad")
recipes.cuisine
recipes.restaurant_name


recipes.describe_restaurant()
recipes.open_restaurant()
Name of restaurant is Shangrilla
Type of cuisine in restaurant is Salad
Shangrilla is open

9-2. Three Restaurants:

  • Start with your class from Exercise 9-1. Create three different instances from the class, and call describe_restaurant() for each instance.
# instance 1
recipes = Restaurant("shangrilla","Salad")

# instance 2
chungi = Restaurant("Chungi 6 restaurant","Chicken karahi")

# instance 3
kfc = Restaurant("KFC Katcheri road","Chicken rolls")

# Calling describe_restaurant for each instance

recipes.describe_restaurant()
chungi.describe_restaurant()
kfc.describe_restaurant()
Name of restaurant is Shangrilla
Type of cuisine in restaurant is Salad
Name of restaurant is Chungi 6 Restaurant
Type of cuisine in restaurant is Chicken Karahi
Name of restaurant is Kfc Katcheri Road
Type of cuisine in restaurant is Chicken Rolls

9-3. Users:

  • Make a class called User. Create two attributes called first_name and last_name, and then create several other attributes that are typically stored in a user profile. Make a method called describe_user() that prints a summary of the user’s information. Make another method called greet_user() that prints a personalized greeting to the user. Create several instances representing different users, and call both methods for each user.
class User:
    def __init__(self,first_name,last_name,password):
        self.first_name = first_name.title()
        self.last_name = last_name.title()
        self.password = password.lower()

    def describe_user(self):
        print(f"Summary of user with first name {self.first_name}, last name {self.last_name} and password is {self.password}")

    def greet_user(self):
        print(f"Hello {self.first_name}. Welcome to the club")

## calling class and saving as instance

first_user = User("shah","nawaz","courses")
second_user = User("malik","hassan","passouts")

first_user.describe_user()
first_user.greet_user()

# like wise we can print for other instance 'second user'
Summary of user with first name Shah, last name Nawaz and password is courses
Hello Shah. Welcome to the club

9-4. Number Served:

  • Start with your program from Exercise 9-1 (page 162). Add an attribute called number_served with a default value of 0. Create an instance called restaurant from this class. Print the number of customers the restaurant has served, and then change this value and print it again.

  • Add a method called set_number_served() that lets you set the number of customers that have been served. Call this method with a new number and print the value again.

  • Add a method called increment_number_served() that lets you increment the number of customers who’ve been served. Call this method with any number you like that could represent how many customers were served in, say, a day of business.

class User:
    def __init__(self,first_name,last_name,password,login_attempts):
        self.first_name = first_name.title()
        self.last_name = last_name.title()
        self.password = password.lower()
        self.login_attempts = login_attempts

    def describe_user(self):
        print(f"Summary of user with first name {self.first_name}, last name {self.last_name} and password is {self.password}")

    def greet_user(self):
        print(f"Hello {self.first_name}. Welcome to the club")
    
    def increment_login_attempts(self,login_attempts):
        self.login_attempts += login_attempts

    def reset_login_attempts(self):
        self.login_attempts = 0


first_user = User("shah","nawaz","courses",3)

first_user.increment_login_attempts(4)
print("Incremented login attempts",first_user.login_attempts)
first_user.increment_login_attempts(42)
print("Incremented login attempts",first_user.login_attempts)
first_user.increment_login_attempts(12)
print("Incremented login attempts",first_user.login_attempts)


first_user.reset_login_attempts()
print("Here login attempts are reset by other method",first_user.login_attempts)
Incremented login attempts 7
Incremented login attempts 49
Incremented login attempts 61
Here login attempts are reset by other method 0

9-5. Login Attempts:

  • Add an attribute called login_attempts to your User class from Exercise 9-3 (page 162). Write a method called increment_login_attempts() that increments the value of login_attempts by 1. Write another method called reset_login_attempts() that resets the value of login_attempts to 0.

  • Make an instance of the User class and call increment_login_attempts() several times. Print the value of login_attempts to make sure it was incremented properly, and then call reset_login_attempts(). Print login_attempts again to make sure it was reset to 0.

class Restaurant:

    def __init__(self,name,cuisine_type):
        self.restaurant_name = name.title()
        self.cuisine = cuisine_type.title()
        self.number_served = 32

    def describe_restaurant(self):
        print(f"Name of restaurant is {self.restaurant_name}")
        print(f"Type of cuisine in restaurant is {self.cuisine}")

    def open_restaurant(self):
        print(f"{self.restaurant_name} is open")

    def set_number_served(self, customers):
        self.number_served = customers
    def incremenet_number_served(self,number_served ):
        self.number_served += number_served
  
restaurant = Restaurant("shangrilla","Salad")

restaurant.set_number_served(34)
restaurant.incremenet_number_served(300)
print(f"Number of customers served are {restaurant.number_served}")
Number of customers served are 334

9-6. Ice Cream Stand:

An ice cream stand is a specific kind of restaurant. Write a class called IceCreamStand that inherits from the Restaurant class you wrote in Exercise 9-1 (page 162) or Exercise 9-4 (page 166). Either version of the class will work; just pick the one you like better. Add an attribute called flavors that stores a list of ice cream flavors. Write a method that displays these flavors. Create an instance of IceCreamStand, and call this method.

class Restaurant:

    def __init__(self,name,cuisine_type):
        self.restaurant_name = name.title()
        self.cuisine = cuisine_type.title()

    def describe_restaurant(self):
        print(f"Name of restaurant is {self.restaurant_name}")
        print(f"Type of cuisine in restaurant is {self.cuisine}")

    def open_restaurant(self):
        print(f"{self.restaurant_name} is open")


class IceCreamStand(Restaurant):

    def __init__(self, name, cuisine_type,flavours):
        super().__init__(name, cuisine_type)
        self.flavours = ['tutti fruitti','chocloate','vanilla']

        # writing method to display flavours
    def display_flavours(self):
        for zaiqa in self.flavours:
            print(f"I like {zaiqa}")

    def for_priting_falvours(self):
        print(self.flavours)


# creating instance of class icecreamStand

galli_wali_icecream = IceCreamStand("butt karahi","chicken karahi","hot")

galli_wali_icecream.display_flavours()

galli_wali_icecream.for_priting_falvours()
I like tutti fruitti
I like chocloate
I like vanilla
['tutti fruitti', 'chocloate', 'vanilla']

9-7. Admin:

An administrator is a special kind of user. Write a class called Admin that inherits from the User class you wrote in Exercise 9-3 (page 162) or Exercise 9-5 (page 167). Add an attribute, privileges, that stores a list of strings like “can add post”, “can delete post”, “can ban user”, and so on. Write a method called show_privileges() that lists the administrator’s set of privileges. Create an instance of Admin, and call your method.

class User:
    def __init__(self,first_name,last_name,password):
        self.first_name = first_name.title()
        self.last_name = last_name.title()
        self.password = password.lower()

    def describe_user(self):
        print(f"Summary of user with first name {self.first_name}, last name {self.last_name} and password is {self.password}")

    def greet_user(self):
        print(f"Hello {self.first_name}. Welcome to the club")


class Admin(User):
    def __init__(self,pvl,first_name,last_name,password):
        super().__init__(first_name,last_name,password)
        self.pvl = ["can write","can edit"]
        


adminuser = Admin(pvl="can write",first_name="malik",last_name = "hasan",password="courses")

adminuser.show_priviliges()

adminuser.greet_user()

9-8. Privileges:

Write a separate Privileges class. The class should have one attribute, privileges, that stores a list of strings as described in Exercise 9-7. Move the show_privileges() method to this class. Make a Privileges instance as an attribute in the Admin class. Create a new instance of Admin and use your method to show its privileges.

class Privileges:
    def __init__(self,privileges):
        self.privileges= ["can write","can edit"]

    def show_priviliges(self):
        for privilige in self.privileges:
            print(f'Admin can {privilige}')

class Admin(User):
    def __init__(self,privileges,first_name,last_name,password,pvl):
        super().__init__(first_name,last_name,password)
        self.pvl = ["can write","can edit"]
        self.privileges = Privileges(privileges)



new_admin = Admin(privileges="can write",first_name="malik",last_name = "hasan",password="courses",pvl=["can host","can read"])

new_admin.privileges.show_priviliges()

9-9. Battery Upgrade:

Use the final version of electric_car.py from this section. Add a method to the Battery class called upgrade_battery(). This method should check the battery size and set the capacity to 65 if it isn’t already. Make an electric car with a default battery size, call get_range() once, and then call get_range() a second time after upgrading the battery. You should see an increase in the car’s range.

class Car:
    def __init__(self, make, model, year):
                            """Initialize attributes to describe a car."""
                            self.make = make
                            self.model = model
                            self.year = year
                            self.odometer_reading = 0
    def get_descriptive_name(self):
            """Return a neatly formatted descriptive name."""
            long_name = f"{self.year} {self.make} {self.model}"
            return long_name.title()
    def read_odometer(self):
            """Print a statement showing the car's mileage."""
            print(f"This car has {self.odometer_reading} miles on it.")
    def update_odometer(self, mileage):
            """Set the odometer reading to the given value."""
            if mileage >= self.odometer_reading:
                self.odometer_reading = mileage
            else:
                print("You can't roll back an odometer!")
    def increment_odometer(self, miles):
            """Add the given amount to the odometer reading."""
            self.odometer_reading += miles

class Battery:
    def __init__(self, battery_size=40):
            """Initialize the battery's attributes."""
            self.battery_size = battery_size
        
        
    def describe_battery(self):
            """Print a statement describing the battery size."""
            print(f"This car has a {self.battery_size}-kWh battery.")

    def get_range(self):
            """Print a statement about the range this battery provides. Make an electric car with a default battery size, call get_range() once, and then call get_range() a second time after upgrading the battery. """
            if self.battery_size == 40:
                range = 150
            elif self.battery_size == 65:
                range = 225
                print(f"This car can go about {range} miles on a full charge.")
            # else:
            #     upgrade_battery(self)
    def upgrade_battery(self):
        if self.battery_size > 65:
                range = 300
                print(f"This car can go about {range} miles on a full charge.")
        
class ElectricCar(Car):
     def __init__(self, make, model, year):
            """Initialize attributes of the parent class. Then initialize attributes specific to an electric car."""
            super().__init__(make, model, year)
            self.battery = Battery()



my_leaf = ElectricCar('nissan', 'leaf', 2024)

my_leaf.battery = Battery(battery_size=75)

my_leaf.battery.upgrade_battery()

print(my_leaf.get_descriptive_name())
my_leaf.battery.describe_battery()
my_leaf.battery.get_range()
This car can go about 300 miles on a full charge.
2024 Nissan Leaf
This car has a 75-kWh battery.

9-10. Imported Restaurant:

Using your latest Restaurant class, store it in a mod- ule. Make a separate file that imports Restaurant. Make a Restaurant instance, and call one of Restaurant’s methods to show that the import statement is work- ing properly.

import restaurant as rs

desi_restautrants = rs.Restaurant("desi tikka", "koftay")

desi_restautrants.open_restaurant()
Desi Tikka is open

9-11. Imported Admin:

Start with your work from Exercise 9-8 (page 173). Store the classes User, Privileges, and Admin in one module. Create a separate file, make an Admin instance, and call show_privileges() to show that everything is working correctly.

import User
from User import Privileges

Admin = Privileges(privileges= ["can write","can edit"])

Admin.show_priviliges() 

9-12. Multiple Modules:

Store the User class in one module, and store the Privileges and Admin classes in a separate module. In a separate file, create an Admin instance and call show_privileges() to show that everything is still working correctly.

from admin import Admin
from Privildges import Privileges


eric = Admin('eric', 'matthes', 'e_matthes', 'e_matthes@example.com', 'alaska')
eric.describe_user()

eric_privileges = [
    'can reset passwords',
    'can moderate discussions',
    'can suspend accounts',
    ]
eric.privileges.privileges = eric_privileges

print(f"\nThe admin {eric.username} has these privileges: ")
eric.privileges.show_privileges()

9-13. Dice:

Make a class Die with one attribute called sides, which has a default value of 6. Write a method called roll_die() that prints a random number between 1 and the number of sides the die has. Make a 6-sided die and roll it 10 times. Make a 10-sided die and a 20-sided die. Roll each die 10 times.

from random import randint


class Die:
  def __init__(self,sides=6):
    self.sides = sides
    
  def roll_die(self):
    print(f"The die has been rolled {randint(1, self.sides)} sides" )

# for 6 sided die    
dana = Die(6)

for i in range(1,11):
  dana.roll_die()

# for 10 sided die
dana = Die(10)

for i in range(1,11):
  dana.roll_die()

# for 20 side die
dana = Die(20)

for i in range(1,11):
  dana.roll_die()
The die has been rolled 6 sides
The die has been rolled 3 sides
The die has been rolled 6 sides
The die has been rolled 4 sides
The die has been rolled 2 sides
The die has been rolled 1 sides
The die has been rolled 1 sides
The die has been rolled 5 sides
The die has been rolled 2 sides
The die has been rolled 5 sides
The die has been rolled 2 sides
The die has been rolled 6 sides
The die has been rolled 7 sides
The die has been rolled 1 sides
The die has been rolled 10 sides
The die has been rolled 4 sides
The die has been rolled 6 sides
The die has been rolled 9 sides
The die has been rolled 10 sides
The die has been rolled 9 sides
The die has been rolled 4 sides
The die has been rolled 20 sides
The die has been rolled 4 sides
The die has been rolled 7 sides
The die has been rolled 10 sides
The die has been rolled 13 sides
The die has been rolled 3 sides
The die has been rolled 17 sides
The die has been rolled 17 sides
The die has been rolled 8 sides

9-14. Lottery:

Make a list or tuple containing a series of 10 numbers and 5 letters. Randomly select 4 numbers or letters from the list and print a message saying that any ticket matching these 4 numbers or letters wins a prize.

from random import choice
quantities = [3,6,5,7,5,'a','t','g','f','e']

for i in range(0,4):
  first_up = choice(quantities)
  print(f"U have won the prize with ticket number {first_up}")
U have won the prize with ticket number 6
U have won the prize with ticket number t
U have won the prize with ticket number 5
U have won the prize with ticket number 6

9-15. Lottery Analysis:

You can use a loop to see how hard it might be to win the kind of lottery you just modeled. Make a list or tuple called my_ticket. Write a loop that keeps pulling numbers until your ticket wins. Print a message report- ing how many times the loop had to run to give you a winning ticket.

# come back later

9-16. Python Module of the Week:

One excellent resource for exploring the Python standard library is a site called Python Module of the Week. Go to https://pymotw.com and look at the table of contents. Find a module that looks interesting to you and read about it, perhaps starting with the random module.