8. 面向对象编程
8.1 类与对象
8.1.1 定义类与创建对象
基本概念:
- 类: 类是一种用户定义的数据类型,它是对象的蓝图。它定义了一组属性(数据成员)和方法(函数),这些属性和方法共同描述了一个实体的行为和状态。
- 对象: 对象是类的实例,即根据类创建的具体实体。每个对象都有自己的属性值,这些值可以通过方法进行修改。
示例代码:
# example_class.py
# 定义一个名为 Person 的类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# 创建 Person 类的一个实例
person1 = Person("Alice", 30)
# 调用 say_hello 方法
person1.say_hello() # 输出: Hello, my name is Alice and I am 30 years old.
8.1.2 类的属性与方法
基本概念:
- 属性: 类的数据成员,可以在类的方法中使用。
- 方法: 类的行为,可以对类的属性进行操作。
示例代码:
# example_attributes_methods.py
# 定义一个名为 Car 的类
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.") # 输出: This car has 0 miles on it.
# 方法: 更新里程表
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!") # 输出: You can't roll back an odometer!
# 创建 Car 类的一个实例
my_car = Car("toyota", "corolla", 2020)
# 调用 get_descriptive_name 方法
print(my_car.get_descriptive_name()) # 输出: 2020 Toyota Corolla
# 调用 read_odometer 方法
my_car.read_odometer() # 输出: This car has 0 miles on it.
# 调用 update_odometer 方法
my_car.update_odometer(10000)
my_car.read_odometer() # 输出: This car has 10000 miles on it.
# 尝试回滚里程表
my_car.update_odometer(9000) # 输出: You can't roll back an odometer!
8.2 构造函数与析构函数
基本概念:
- 构造函数: 在创建对象时被自动调用的特殊方法,通常用来初始化对象的属性。
- 析构函数: 在对象被销毁前被调用的特殊方法,在 Python 中通常不需要显式使用。
示例代码:
# example_constructors_destructors.py
class Animal:
def __init__(self, name): # 构造函数
self.name = name
print(f"{self.name} was born!") # 输出: Alice was born!
def speak(self):
pass
def __del__(self): # 析构函数
print(f"{self.name} says goodbye.") # 输出: Alice says goodbye.
# 创建 Animal 类的一个实例
alice = Animal("Alice")
# 调用 speak 方法 (未实现)
# alice.speak()
# 由于 Python 的垃圾回收机制,析构函数通常不需要显式调用
8.3 继承与多态
基本概念:
- 继承: 允许创建一个新类(子类),它继承了现有类(父类)的所有属性和方法。
- 多态: 不同类的对象可以响应相同的方法名,但具有不同的行为。
示例代码:
# example_inheritance_polymorphism.py
class Vehicle:
def __init__(self, make, model):
self.make = make
self.model = model
def drive(self):
print("Driving...")
def stop(self):
print("Stopping...")
# 定义 Car 类,继承自 Vehicle
class Car(Vehicle):
def __init__(self, make, model, year):
super().__init__(make, model) # 调用父类的构造函数
self.year = year
def drive(self): # 方法重写
print("Driving a car...") # 输出: Driving a car...
# 定义 Motorcycle 类,继承自 Vehicle
class Motorcycle(Vehicle):
def __init__(self, make, model, year):
super().__init__(make, model)
self.year = year
def drive(self): # 方法重写
print("Riding a motorcycle...") # 输出: Riding a motorcycle...
# 创建 Car 和 Motorcycle 的实例
car = Car("Toyota", "Corolla", 2020)
motorcycle = Motorcycle("Honda", "CBR", 2021)
# 多态示例
vehicles = [car, motorcycle]
for vehicle in vehicles:
vehicle.drive() # 输出: Driving a car...
# Riding a motorcycle...
8.4 方法重写与重载
基本概念:
- 方法重写: (Method Overriding): 当子类继承父类时,子类可以重新定义父类的方法。这意味着子类中的方法与父类中的方法同名,但在子类中实现了不同的功能。当子类的对象调用该方法时,将执行子类中定义的方法。
示例代码:
# example_method_overriding.py
class Shape:
def area(self):
print("Calculating area...")
# 定义 Circle 类,继承自 Shape
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self): # 方法重写
area = 3.14 * self.radius ** 2
print(f"The area of the circle is {area:.2f}") # 输出: The area of the circle is 31.42
# 创建 Circle 类的一个实例
circle = Circle(3)
circle.area() # 输出: The area of the circle is 31.42
- 方法重载 (Method Overloading): 在 Python 中,方法重载不像其他一些语言(如 Java 或 C++)那样直接支持。然而,可以通过定义多个同名但参数不同的方法来模拟方法重载的行为。Python 中的方法重载通常是通过使用可变数量的参数(如
*args
和**kwargs
)来实现的。
# example_method_overloading.py
# 定义一个名为 Calculator 的类
class Calculator:
def add(self, *args):
"""模拟方法重载"""
sum = 0
for arg in args:
sum += arg
return sum
# 创建 Calculator 类的一个实例
calc = Calculator()
# 调用 add 方法
print(calc.add(10, 20)) # 输出: 30
print(calc.add(10, 20, 30)) # 输出: 60
print(calc.add(10, 20, 30, 40)) # 输出: 100
8.5 类属性与实例属性
基本概念:
- 实例属性: 与特定实例相关联的属性。
- 类属性: 与整个类相关联的属性,所有实例共享同一个值。
示例代码:
# example_class_instance_attributes.py
class Employee:
# 类属性
raise_amount = 1.05 # 默认加薪比例
def __init__(self, first, last, pay):
# 实例属性
self.first = first
self.last = last
self.pay = pay
self.email = f"{first}.{last}@company.com"
# 方法: 应用加薪
def apply_raise(self):
self.pay = int(self.pay * self.raise_amount) # 使用类属性
# 方法: 显示员工信息
def display_info(self):
print(f"Employee: {self.first} {self.last}, Email: {self.email}, Pay: {self.pay}") # 输出: Employee: John Doe, Email: john.doe@company.com, Pay: 52500
# 创建 Employee 类的实例
employee1 = Employee("John", "Doe", 50000)
# 调用 display_info 方法
employee1.display_info() # 输出: Employee: John Doe, Email: john.doe@company.com, Pay: 50000
# 应用加薪
employee1.apply_raise()
employee1.display_info() # 输出: Employee: John Doe, Email: john.doe@company.com, Pay: 52500
# 修改实例的类属性
employee1.raise_amount = 1.10
employee1.apply_raise()
employee1.display_info() # 输出: Employee: John Doe, Email: john.doe@company.com, Pay: 57750
8.6 静态方法与类方法
基本概念:
- 静态方法: 不需要访问类或实例的状态,通常用于与类相关但不依赖于类实例的方法。
- 类方法: 通过第一个参数
cls
访问类本身,通常用于创建类的新实例或其他与类相关的方法。
示例代码:
# example_static_class_methods.py
class Date:
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_str):
day, month, year = map(int, date_str.split('-'))
return cls(day, month, year) # 返回 Date 类的新实例
@staticmethod
def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) # 输出: True
# 使用类方法创建 Date 类的实例
date1 = Date.from_string("29-02-2020")
print(date1.day, date1.month, date1.year) # 输出: 29 2 2020
# 使用静态方法
print(Date.is_leap_year(2020)) # 输出: True
8.7 类与对象的内置函数
基本概念:
- 内置函数: Python 为类和对象提供了许多内置函数,如
str()
,repr()
,len()
,getattr()
,setattr()
,delattr()
等。
示例代码:
# example_builtin_functions.py
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
def __str__(self):
return f"{self.title} by {self.author}" # 输出: The Catcher in the Rye by J.D. Salinger
def __repr__(self):
return f"Book('{self.title}', '{self.author}', {self.pages})" # 输出: Book('The Catcher in the Rye', 'J.D. Salinger', 277)
def __len__(self):
return self.pages # 输出: 277
# 创建 Book 类的一个实例
book = Book("The Catcher in the Rye", "J.D. Salinger", 277)
# 使用 str() 函数
print(str(book)) # 输出: The Catcher in the Rye by J.D. Salinger
# 使用 repr() 函数
print(repr(book)) # 输出: Book('The Catcher in the Rye', 'J.D. Salinger', 277)
# 使用 len() 函数
print(len(book)) # 输出: 277
# 使用 getattr() 函数
print(getattr(book, "title")) # 输出: The Catcher in the Rye
# 使用 setattr() 函数
setattr(book, "author", "J.D. Salinger (Revised)")
print(book.author) # 输出: J.D. Salinger (Revised)
# 使用 delattr() 函数
delattr(book, "pages")
print(book.__dict__) # 输出: {'title': 'The Catcher in the Rye', 'author': "J.D. Salinger (Revised)"}