Basic class
A class is made up of methods and state. This allows code and data to be combined as one logical entity. This module defines a basic car class, creates a car instance and uses it for demonstration purposes.
from inspect import isfunction, ismethod, signature
class Car:
"""Basic definition of a car.
We begin with a simple mental model of what a car is. That way, we
can start exploring the core concepts that are associated with a
class definition.
"""
def __init__(self, make, model, year, miles):
"""Constructor logic."""
self.make = make
self.model = model
self.year = year
self.miles = miles
def __repr__(self):
"""Formal representation for developers."""
return f"<Car make={self.make} model={self.model} year={self.year}>"
def __str__(self):
"""Informal representation for users."""
return f"{self.make} {self.model} ({self.year})"
def drive(self, rate_in_mph):
"""Drive car at a certain rate in MPH."""
return f"{self} is driving at {rate_in_mph} MPH"
def main():
# Create a car with the provided class constructor
car = Car("Bumble", "Bee", 2000, 200000.0)
# Formal representation is good for debugging issues
assert repr(car) == "<Car make=Bumble model=Bee year=2000>"
# Informal representation is good for user output
assert str(car) == "Bumble Bee (2000)"
# Call a method on the class constructor
assert car.drive(75) == "Bumble Bee (2000) is driving at 75 MPH"
# As a reminder: everything in Python is an object! And that applies
# to classes in the most interesting way - because they're not only
# subclasses of object - they are also instances of object. This
# means that we can modify the `Car` class at runtime, just like any
# other piece of data we define in Python
assert issubclass(Car, object) and isinstance(Car, object)
# To emphasize the idea that everything is an object, let's look at
# the `drive` method in more detail
driving = getattr(car, "drive")
# The variable method is the same as the instance method
assert driving == car.drive
# The variable method is bound to the instance
assert driving.__self__ == car
# That is why `driving` is considered a method and not a function
assert ismethod(driving) and not isfunction(driving)
# And there is only one parameter for `driving` because `__self__`
# binding is implicit
driving_params = signature(driving).parameters
assert len(driving_params) == 1
assert "rate_in_mph" in driving_params
if __name__ == "__main__":
main()