Object-oriented programming (面向对象编程) is one of the most effective approaches to writing software.
Python has been an object-oriented language since it existed. Because of this, creating and using classes and objects are downright easy.
Understanding object-oriented programming will help you see the world as a programmer does. It'll help you really know your code, not just what's happening line by line, but also the bigger concepts behind it.
Creating and Using a Class (类)
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def sit(self):
print(f"{self.name.title()} is now sitting.")
def roll_over(self):
print(f"{self.name.title()} rolled over!")
By convention, capitalized names refer to classes in Python.
A function that's part of a class is a method (方法).
The __init__() method is a special method Python runs automatically whenever we create a new instance (实例) based on the Dog class.
Variables that are accessible through instances like this are called attributes (属性).
Making an Instance from a Class
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def sit(self):
print(f"{self.name.title()} \
is now sitting.")
def roll_over(self):
print(f"{self.name.title()} \
rolled over!")
my_dog = Dog('willie', 6)
print(my_dog.name.title())
print(str(my_dog.age)+" years old")
Willie
6 years old
my_dog.sit()
my_dog.roll_over()
Willie is now sitting.
Willie rolled over!
your_dog = Dog('lucy', 3)
Working with Classes and Instances
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make}\
{self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has\
{self.odometer_reading}\
miles on it.")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
2016 Audi A4
This car has 0 miles on it.
Modifying Attribute Values
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def read_odometer(self):
print(f"This car has\
{self.odometer_reading}\
miles on it.")
Modifying an Attribute's Value Directly
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
2016 Audi A4
This car has 23 miles on it.
Modifying Attribute Values
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def read_odometer(self):
print(f"This car has\
{self.odometer_reading}\
miles on it.")
def update_odometer(self, mileage):
self.odometer_reading = mileage
Modifying an Attribute's Value Through a Method
my_new_car = Car('audi', 'a4', 2016)
my_new_car.update_odometer(23)
my_new_car.read_odometer()
This car has 23 miles on it.
my_new_car.update_odometer(30)
my_new_car.read_odometer()
This car has 30 miles on it.
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def read_odometer(self):
print(f"This car has\
{self.odometer_reading}\
miles on it.")
def update_odometer(self, mileage):
self.odometer_reading = mileage
def increment_odometer(self, miles):
self.odometer_reading \
= self.odometer_reading + miles
Modifying an Attribute's Value Through a Method
my_new_car = Car('audi', 'a4', 2016)
my_new_car.update_odometer(23)
my_new_car.read_odometer()
This car has 23 miles on it.
my_new_car.increment_odometer(100)
my_new_car.read_odometer()
This car has 123 miles on it.
You don't always have to start from scratch when writing a class. If the class you're writing is a specialized version of another class you wrote, you can use inheritance.
When one class inherits from another, it automatically takes on all the attributes and methods of the first class.
The original class is called the parent class, and the new class is the child class. The child class inherits every attribute and method from its parent class but is also free to define new attributes and methods of its own.
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make}\
{self.model}"
return long_name.title()
class ElectricCar(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2016 Tesla Model S
Defining attributes and methods for the child class
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make}\
{self.model}"
return long_name.title()
class ElectricCar(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery_size = 70
def describe_battery(self):
print(f"{self.battery_size}-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
2016 Tesla Model S
70-kWh battery.
Overriding methods from the parent class
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name=f"{self.year} {self.make}\
{self.model}"
return long_name.title()
class ElectricCar(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery_size = 70
def describe_battery(self):
print(f"{self.battery_size}-kWh battery.")
def get_descriptive_name(self):
long_name=f"{self.year} {self.make}"
return long_name.title()
Open/closed principle
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
class Person:
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person):
pass
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()
May female Peter male
woman
man
class Person:
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person):
def __init__(self,name,sex):
Person.__init__(self,name,sex)
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()
May female Peter male
woman
man
Overwrite completely
class Person:
def __init__(self,name,sex):
self.name = name
self.sex = sex
class Child(Person):
def __init__(self,name,sex,mother):
self.name = name
self.sex = sex
self.mother = mother
May = Child("May","female","April")
print(May.name,May.sex,May.mother)
May female April
Overwrite partially
class Person:
def __init__(self,name,sex):
self.name = name
self.sex = sex
class Child(Person):
def __init__(self,name,sex,mother):
Person.__init__(self,name,sex)
#super().__init__(name,sex)
self.mother = mother
May = Child("May","female","April")
print(May.name,May.sex,May.mother)
May female April
If you just need complete inheritance of attributes, then all three ways are equivalent.
class Person:
pass
class Child(Person):
pass
May = Child()
Peter = Person()
print(isinstance(May,Child)) # True
print(isinstance(May,Person)) # True
print(isinstance(Peter,Child)) # False
print(isinstance(Peter,Person)) # True
print(issubclass(Child,Person)) # True
The precise definition of dir() is that it lists the methods and attributes of a Python object.
>>> stuff = list()
>>> dir(stuff)
['__add__', '__class__', '__contains__', '__delattr__',
'__delitem__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__getitem__',
'__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
'__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__',
'__setitem__', '__sizeof__', '__str__', '__subclasshook__',
'append', 'clear', 'copy', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
Everything in Python is an object.
stuff = []
stuff.append('python')
stuff.append('chuck')
stuff.sort()
print(stuff[0])
print(stuff.__getitem__(0))
print(list.__getitem__(stuff,0))
chuck
chuck
chuck
Actually, the class you create inherits the "object" class.
Classes can intercept Python Operators
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
my_dog = Dog('willie', 6)
print(dir(my_dog))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age', 'name']
__str__
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
my_dog = Dog('willie', 6)
print(my_dog)
<__main__.Dog object at 0x053A3750>
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name
my_dog = Dog('willie', 6)
print(my_dog)
willie
__doc__, __name__, __module__, __bases__
class Dog():
"This is about dog class."
def __init__(self, name, age):
self.name = name
self.age = age
print(Dog.__doc__)
print(Dog.__name__)
print(Dog.__module__)
print(Dog.__bases__)
This is about dog class.
Dog
__main__
(<class 'object'>,)
class Dog():
"This is about dog class."
def __init__(self, name, age):
self.name = name
self.age = age
class Husky(Dog):
pass
print(Husky.__bases__)
(<class '__main__.Dog'>,)
Importing a Single Class
Save your Car class in a python file: car.py
from car import Car
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
2016 Audi A4
This car has 23 miles on it.
Storing Multiple Classes in a Module
You can store as many classes as you need in a single module, although each class in a module should be related somehow.
from car import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2016 Tesla Model S
Importing Multiple Classes from a Module
from car import Car, ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
2016 Volkswagen Beetle
2016 Tesla Roadster
Importing a Module into a Module
car.py
class Car():
...
electric_car.py
from car import Car
class Battery():
...
class ElectricCar(Car):
...
my_cars.py
from car import Car
from electric_car import ElectricCar
Three Features of OOP
Encapsulation, inheritance, polymorphism
Everything in Python is object.
Process-oriented programming (POP)
Object-oriented Programming (OOP)