<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Instance Attributes and Methods
(source
Step1:  Static Methods
Don't have access to self.
Step2:  Our make_car_sound static method does not work on an instance of our Car class because the instance tries to pass a self arg.
To get around this, we use something called a decorator. In python, decorators start with the @ sign.
Step3:  Class Methods
Previously we passed instances of a class to our methods using self. For class methods, we pass the whole class (not just a specific instance)
Step8:  Inheritance
While Object-oriented Programming is useful as a modeling tool, it truly gains power when the concept of inheritance is introduced. Inherticance is the process by which a "child" class derives the data and behavior of a "parent" class. An example will definitely help us here.
Imagine we run a car dealership. We sell all types of vehicles, from motorcycles to trucks. We set ourselves apart from the competition by our prices. Specifically, how we determine the price of a vehicle on our lot
Step13:  Okay, now let's create a truck class
Step18:  There's a lot of overlap between the car class and the truck class. In the spirit of DRY (don't repeat yourself), we'll try and abstract away the specific differences between car and truck and instead implement an abstract vehicle class.
Abstract Classes
Step21:  Now we can make the Car and Truck class inherit from the Vehicle class by replacing object in the line class Car(object). The class in parenthesis is the class that is inherited from (object essentially means "no inheritance". We'll discuss exactly why we write that in a bit).
Step22:  This is okay, but we're still repeating a lot of code. We'd really like to get rid of all repetition.
More problematic is people will be able to make a vehicle object. Do we really want people to make abstract objects (as opposed to cars and trucks) in this case?
A Vehicle is just a concept, not a real thing, so what does it mean to say the following
Step23:  A Vehicle doesn't have a base_sale_price, only the individual child classes like Car and Truck do. The issue is that Vehicle should really be an Abstract Base Class. 
Abstract Base Classes are classes that are only meant to be inherited from; you can't create instance of an ABC. That means that, if Vehicle is an ABC, the following is illegal
Step28:  It makes sense to disallow this, as we never meant for vehicles to be used directly. We just wanted to use it to abstract away some common data and behavior. So how do we make a class an ABC? Simple! The abc module contains a metaclass called ABCMeta (metaclasses are a bit outside the scope of this article).
Setting a class's metaclass to ABCMeta and making one of its methods virtual makes it an ABC. A virtual method is one that the ABC says must exist in child classes, but doesn't necessarily actually implement. For example, the Vehicle class may be defined as follows
Step37:  Now, since vehicle_type is an abstractmethod, we can't directly create an instance of Vehicle. As long as Car and Truck inherit from Vehicle and define vehicle_type, we can instantiate those classes just fine.
Returning to the repetition in our Car and Truck classes, let see if we can't remove that by hoisting up common functionality to the base class, Vehicle
Step40:  This fits perfectly with our intuition
Step41:  Inheritance and the LSP
So far, we've seen how using inheritance reduced duplication. What we were really doing was providing the proper level of abstraction.
We've been working from the perspective of the object builder but what about the object caller's perspective?
Quite a bit, it turns out. Imagine we have two classes, Dog and Person, and we want to write a function that takes either type of object and prints out whether or not the instance in question can speak (a dog can't, a person can). We might write code like the following
Step42:  That works when we only have two types of animals, but what if we have twenty, or two hundred? That if...elif chain is going to get quite long.
The key insight here is that can_speak shouldn't care what type of animal it's dealing with, the animal class itself should tell us if it can speak. By introducing a common base class, Animal, that defines can_speak, we relieve the function of it's type-checking burden. Now, as long as it knows it was an Animal that was passed in, determining if it can speak is trivial
<ASSISTANT_TASK:>
Python Code:
class Car(object):
    wheels = 4 
    def __init__(self, make, model):
        self.make = make
        self.model = model
mustang = Car('Ford', 'Mustang')
print(mustang.wheels)
# 4
print(Car.wheels)
# 4
Explanation: Instance Attributes and Methods
(source: Jeff Knupp)
Class attributes
Class attributes are attributes that are set at the class-level, as opposed to the instance-level. Normal attributes are introduced in the init method, but some attributes of a class hold for all instances in all cases. For example, consider the following definition of a Car object:
End of explanation
class Car(object):
    ...
    def make_car_sound():
        print('VRooooommmm!')
Car.make_car_sound() # This works
ford = Car()
ford.make_car_sound() # This doesn't
Explanation: Static Methods
Don't have access to self.
End of explanation
class Car(object):
    
    wheels = 4 
    
    @staticmethod
    def make_car_sound():
        print('VRooooommmm!')
         
    def __init__(self, make, model):
        self.make = make
        self.model = model
Car.make_car_sound(6)
ford = Car('Ford', 'Falcon')
ford.make_car_sound() # This works now!
Explanation: Our make_car_sound static method does not work on an instance of our Car class because the instance tries to pass a self arg.
To get around this, we use something called a decorator. In python, decorators start with the @ sign.
End of explanation
class Vehicle(object):
    ...
    wheels = 4
    
    @classmethod
    def is_motorcycle(cls):
        return cls.wheels == 2
Vehicle.is_motorcycle() 
Explanation: Class Methods
Previously we passed instances of a class to our methods using self. For class methods, we pass the whole class (not just a specific instance):
End of explanation
class Car(object):
    A car for sale by Jeffco Car Dealership.
    Attributes:
        wheels: An integer representing the number of wheels the car has.
        miles: The integral number of miles driven on the car.
        make: The make of the car as a string.
        model: The model of the car as a string.
        year: The integral year the car was built.
        sold_on: The date the vehicle was sold.
    
    def __init__(self, wheels, miles, make, model, year, sold_on):
        Return a new Car object.
        self.wheels = wheels
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
    def sale_price(self):
        Return the sale price for this car as a float amount.
        if self.sold_on is not None:
            return 0.0  # Already sold
        return 5000.0 * self.wheels
    def purchase_price(self):
        Return the price for which we would pay to purchase the car.
        if self.sold_on is None:
            return 0.0  # Not yet sold
        return 8000 - (.10 * self.miles)
    ...
Explanation: Inheritance
While Object-oriented Programming is useful as a modeling tool, it truly gains power when the concept of inheritance is introduced. Inherticance is the process by which a "child" class derives the data and behavior of a "parent" class. An example will definitely help us here.
Imagine we run a car dealership. We sell all types of vehicles, from motorcycles to trucks. We set ourselves apart from the competition by our prices. Specifically, how we determine the price of a vehicle on our lot: \$5,000 x number of wheels a vehicle has. We love buying back our vehicles as well. We offer a flat rate - 10% of the miles driven on the vehicle. For trucks, that rate is \$10,000. For cars, \$8,000. For motorcycles, \$4,000.
If we wanted to create a sales system for our dealership using Object-oriented techniques, how would we do so? What would the objects be? We might have a Sale class, a Customer class, an Inventory class, and so forth, but we'd almost certainly have a Car, Truck, and Motorcycle class.
What would these classes look like? Using what we've learned, here's a possible implementation of the Car class:
End of explanation
class Truck(object):
    A truck for sale by Jeffco Car Dealership.
    Attributes:
        wheels: An integer representing the number of wheels the truck has.
        miles: The integral number of miles driven on the truck.
        make: The make of the truck as a string.
        model: The model of the truck as a string.
        year: The integral year the truck was built.
        sold_on: The date the vehicle was sold.
    
    def __init__(self, wheels, miles, make, model, year, sold_on):
        Return a new Truck object.
        self.wheels = wheels
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
    def sale_price(self):
        Return the sale price for this truck as a float amount.
        if self.sold_on is not None:
            return 0.0  # Already sold
        return 5000.0 * self.wheels
    def purchase_price(self):
        Return the price for which we would pay to purchase the truck.
        if self.sold_on is None:
            return 0.0  # Not yet sold
        return 10000 - (.10 * self.miles)
Explanation: Okay, now let's create a truck class:
End of explanation
class Vehicle(object):
    A vehicle for sale by Jeffco Car Dealership.
    Attributes:
        wheels: An integer representing the number of wheels the vehicle has.
        miles: The integral number of miles driven on the vehicle.
        make: The make of the vehicle as a string.
        model: The model of the vehicle as a string.
        year: The integral year the vehicle was built.
        sold_on: The date the vehicle was sold.
    
    base_sale_price = 0
    def __init__(self, wheels, miles, make, model, year, sold_on):
        Return a new Vehicle object.
        self.wheels = wheels
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
    def sale_price(self):
        Return the sale price for this vehicle as a float amount.
        if self.sold_on is not None:
            return 0.0  # Already sold
        return 5000.0 * self.wheels
    def purchase_price(self):
        Return the price for which we would pay to purchase the vehicle.
        if self.sold_on is None:
            return 0.0  # Not yet sold
        return self.base_sale_price - (.10 * self.miles)
Explanation: There's a lot of overlap between the car class and the truck class. In the spirit of DRY (don't repeat yourself), we'll try and abstract away the specific differences between car and truck and instead implement an abstract vehicle class.
Abstract Classes
End of explanation
class Car(Vehicle):
    def __init__(self, wheels, miles, make, model, year, sold_on):
        Return a new Car object.
        self.wheels = wheels
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
        self.base_sale_price = 8000
        
        
class Truck(Vehicle):
    def __init__(self, wheels, miles, make, model, year, sold_on):
        Return a new Truck object.
        self.wheels = wheels
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
        self.base_sale_price = 10000
Explanation: Now we can make the Car and Truck class inherit from the Vehicle class by replacing object in the line class Car(object). The class in parenthesis is the class that is inherited from (object essentially means "no inheritance". We'll discuss exactly why we write that in a bit).
End of explanation
v = Vehicle(4, 0, 'Honda', 'Accord', 2014, None)
print(v.purchase_price())
Explanation: This is okay, but we're still repeating a lot of code. We'd really like to get rid of all repetition.
More problematic is people will be able to make a vehicle object. Do we really want people to make abstract objects (as opposed to cars and trucks) in this case?
A Vehicle is just a concept, not a real thing, so what does it mean to say the following:
End of explanation
v = Vehicle(4, 0, 'Honda', 'Accord', 2014, None)
Explanation: A Vehicle doesn't have a base_sale_price, only the individual child classes like Car and Truck do. The issue is that Vehicle should really be an Abstract Base Class. 
Abstract Base Classes are classes that are only meant to be inherited from; you can't create instance of an ABC. That means that, if Vehicle is an ABC, the following is illegal:
End of explanation
from abc import ABCMeta, abstractmethod
class Vehicle(object):
    A vehicle for sale by Jeffco Car Dealership.
    Attributes:
        wheels: An integer representing the number of wheels the vehicle has.
        miles: The integral number of miles driven on the vehicle.
        make: The make of the vehicle as a string.
        model: The model of the vehicle as a string.
        year: The integral year the vehicle was built.
        sold_on: The date the vehicle was sold.
    
    __metaclass__ = ABCMeta
    base_sale_price = 0
    def sale_price(self):
        Return the sale price for this vehicle as a float amount.
        if self.sold_on is not None:
            return 0.0  # Already sold
        return 5000.0 * self.wheels
    def purchase_price(self):
        Return the price for which we would pay to purchase the vehicle.
        if self.sold_on is None:
            return 0.0  # Not yet sold
        return self.base_sale_price - (.10 * self.miles)
    @abstractmethod
    def vehicle_type():
        "Return a string representing the type of vehicle this is.
        pass
v = Vehicle()
v.base_sale_price
Explanation: It makes sense to disallow this, as we never meant for vehicles to be used directly. We just wanted to use it to abstract away some common data and behavior. So how do we make a class an ABC? Simple! The abc module contains a metaclass called ABCMeta (metaclasses are a bit outside the scope of this article).
Setting a class's metaclass to ABCMeta and making one of its methods virtual makes it an ABC. A virtual method is one that the ABC says must exist in child classes, but doesn't necessarily actually implement. For example, the Vehicle class may be defined as follows:
End of explanation
from abc import ABCMeta, abstractmethod
class Vehicle(object):
    A vehicle for sale by Jeffco Car Dealership.
    Attributes:
        wheels: An integer representing the number of wheels the vehicle has.
        miles: The integral number of miles driven on the vehicle.
        make: The make of the vehicle as a string.
        model: The model of the vehicle as a string.
        year: The integral year the vehicle was built.
        sold_on: The date the vehicle was sold.
    
    __metaclass__ = ABCMeta
    base_sale_price = 0
    wheels = 0
    def __init__(self, miles, make, model, year, sold_on):
        self.miles = miles
        self.make = make
        self.model = model
        self.year = year
        self.sold_on = sold_on
    def sale_price(self):
        Return the sale price for this vehicle as a float amount.
        if self.sold_on is not None:
            return 0.0  # Already sold
        return 5000.0 * self.wheels
    def purchase_price(self):
        Return the price for which we would pay to purchase the vehicle.
        if self.sold_on is None:
            return 0.0  # Not yet sold
        return self.base_sale_price - (.10 * self.miles)
    @abstractmethod
    def vehicle_type(self):
        "Return a string representing the type of vehicle this is.
        pass
class Car(Vehicle):
    A car for sale by Jeffco Car Dealership.
    base_sale_price = 8000
    wheels = 4
    def vehicle_type(self):
        "Return a string representing the type of vehicle this is.
        return 'car'
class Truck(Vehicle):
    A truck for sale by Jeffco Car Dealership.
    base_sale_price = 10000
    wheels = 4
    def vehicle_type(self):
        "Return a string representing the type of vehicle this is.
        return 'truck'
Explanation: Now, since vehicle_type is an abstractmethod, we can't directly create an instance of Vehicle. As long as Car and Truck inherit from Vehicle and define vehicle_type, we can instantiate those classes just fine.
Returning to the repetition in our Car and Truck classes, let see if we can't remove that by hoisting up common functionality to the base class, Vehicle:
End of explanation
class Motorcycle(Vehicle):
    A motorcycle for sale by Jeffco Car Dealership.
    base_sale_price = 4000
    wheels = 2
    def vehicle_type(self):
        "Return a string representing the type of vehicle this is.
        return 'motorcycle'
honda = Car(0, 'Honda', 'Accord', 2014, None)
honda.wheels
suzuki = Motorcycle(0, 'Suzuki', 'Ninja', 2015, None)
suzuki.wheels
Explanation: This fits perfectly with our intuition: as far as our system is concerned, the only difference between a car and truck is the base sale price. Defining a Motorcycle class, then, is similarly simple:
End of explanation
def can_speak(animal):
    if isinstance(animal, Person):
        return True
    elif isinstance(animal, Dog):
        return False
    else:
        raise RuntimeError('Unknown animal!')
Explanation: Inheritance and the LSP
So far, we've seen how using inheritance reduced duplication. What we were really doing was providing the proper level of abstraction.
We've been working from the perspective of the object builder but what about the object caller's perspective?
Quite a bit, it turns out. Imagine we have two classes, Dog and Person, and we want to write a function that takes either type of object and prints out whether or not the instance in question can speak (a dog can't, a person can). We might write code like the following:
End of explanation
def can_speak(animal):
    return animal.can_speak()
Explanation: That works when we only have two types of animals, but what if we have twenty, or two hundred? That if...elif chain is going to get quite long.
The key insight here is that can_speak shouldn't care what type of animal it's dealing with, the animal class itself should tell us if it can speak. By introducing a common base class, Animal, that defines can_speak, we relieve the function of it's type-checking burden. Now, as long as it knows it was an Animal that was passed in, determining if it can speak is trivial:
End of explanation
<END_TASK>