Python 学习教程 - 第四篇:面向对象编程
欢迎继续 Python 学习之旅!今天我们将学习 Python 最强大的特性之一:面向对象编程(OOP)。
目录
面向对象编程基础
什么是面向对象编程?
面向对象编程是一种编程范式,它将程序组织成"对象",每个对象包含数据和操作数据的方法。
面向对象 vs 面向过程
面向过程(过程式编程):
- 关注"怎么做"
- 函数和过程是主要构建块
- 数据和操作数据的函数分离
面向对象(OOP):
- 关注"谁来做"
- 类和对象是主要构建块
- 数据和操作数据的函数封装在一起
OOP 的三大特性
- 封装(Encapsulation):隐藏内部实现,只暴露必要接口
- 继承(Inheritance):代码复用,建立类之间的关系
- 多态(Polymorphism):同一接口,不同实现
类和对象
类的定义
类是对象的蓝图或模板。
# 定义一个简单的类
class Dog:
"""狗类"""
# 类属性
species = "哺乳动物"
def __init__(self, name, age):
"""构造函数:创建对象时自动调用"""
self.name = name # 实例属性
self.age = age # 实例属性
# 实例方法
def bark(self):
"""狗叫的方法"""
print(f"{self.name} 汪汪叫!")
def introduce(self):
"""自我介绍"""
print(f"我是 {self.name},{self.age} 岁,是 {self.species}")
# 创建对象(实例化)
dog1 = Dog("旺财", 3)
dog2 = Dog("小黄", 5)
# 调用方法
dog1.bark() # 旺财 汪汪叫!
dog2.bark() # 小黄 汪汪叫!
dog1.introduce() # 我是 旺财,3 岁,是 哺乳动物
dog2.introduce() # 我是 小黄,5 岁,是 哺乳动物
对象和类的关系
- 类:抽象的概念,定义了对象的属性和方法
- 对象:类的实例,具体的实体
- 实例化:从类创建对象的过程
构造函数和初始化
__init__ 方法
__init__ 是构造函数,在创建对象时自动调用。
class Person:
def __init__(self, name, age, gender):
"""初始化方法"""
self.name = name
self.age = age
self.gender = gender
def get_info(self):
"""获取信息"""
return f"{self.name}, {self.age}岁, {self.gender}"
# 创建对象
p1 = Person("张三", 25, "男")
p2 = Person("李四", 30, "女")
print(p1.get_info()) # 张三, 25岁, 男
print(p2.get_info()) # 李四, 30岁, 女
默认参数
可以为构造函数提供默认参数。
class Person:
def __init__(self, name, age=18, gender="未知"):
self.name = name
self.age = age
self.gender = gender
# 使用默认参数
p1 = Person("张三") # 使用默认值
p2 = Person("李四", 25) # 只提供年龄
p3 = Person("王五", 30, "男") # 全部参数
print(p1.name, p1.age, p1.gender) # 张三 18 未知
print(p2.name, p2.age, p2.gender) # 李四 25 未知
print(p3.name, p3.age, p3.gender) # 王五 30 男
自定义构造函数
可以重载 __new__ 方法来控制对象创建过程。
class Counter:
_count = 0 # 类变量
def __new__(cls):
cls._count += 1
return super().__new__(cls)
def __init__(self):
self.id = Counter._count
# 创建多个对象
c1 = Counter()
c2 = Counter()
c3 = Counter()
print(c1.id) # 1
print(c2.id) # 2
print(c3.id) # 3
print(Counter._count) # 3
属性和方法
实例属性 vs 类属性
实例属性:每个对象独有的属性
class Car:
brand = "Toyota" # 类属性(所有对象共享)
def __init__(self, model, color):
self.model = model # 实例属性
self.color = color # 实例属性
car1 = Car("Camry", "红色")
car2 = Car("Corolla", "蓝色")
print(car1.brand) # Toyota(类属性)
print(car1.model) # Camry(实例属性)
print(car2.brand) # Toyota(类属性)
print(car2.model) # Corolla(实例属性)
实例方法 vs 类方法 vs 静态方法
class MathUtil:
# 实例方法:需要 self 参数
def add(self, a, b):
return a + b
# 类方法:需要 cls 参数,操作类属性
@classmethod
def multiply(cls, a, b):
return a * b
# 静态方法:不需要 self 或 cls
@staticmethod
def power(a, b):
return a ** b
# 实例方法
mu = MathUtil()
print(mu.add(2, 3)) # 5
# 类方法
print(MathUtil.multiply(2, 3)) # 6
# 静态方法
print(MathUtil.power(2, 3)) # 8
Getter 和 Setter
使用 @property 装饰器创建属性访问器。
class Person:
def __init__(self, name, age):
self._name = name # 私有属性(约定以 _ 开头)
self._age = age
# Getter
@property
def name(self):
return self._name
@property
def age(self):
return self._age
# Setter
@name.setter
def name(self, new_name):
if len(new_name) > 0:
self._name = new_name
else:
print("名字不能为空!")
@age.setter
def age(self, new_age):
if new_age >= 0:
self._age = new_age
else:
print("年龄不能为负数!")
# 使用
p = Person("张三", 25)
print(p.name) # 张三
print(p.age) # 25
p.name = "李四" # 通过 setter 修改
print(p.name) # 李四
p.age = 30
print(p.age) # 30
p.age = -5 # 不会修改,会打印错误信息
print(p.age) # 30
封装
封装的概念
封装是指隐藏对象的内部实现细节,只暴露必要的接口。在 Python 中,通过命名约定和访问修饰符实现封装。
私有属性和方法
Python 中没有真正的私有属性,但约定以 _ 开头表示私有。
class BankAccount:
def __init__(self, account_number, balance):
self.account_number = account_number
self._balance = balance # 受保护的属性
def deposit(self, amount):
"""存款"""
if amount > 0:
self._balance += amount
print(f"存款 {amount} 元成功")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
"""取款"""
if amount > 0 and amount <= self._balance:
self._balance -= amount
print(f"取款 {amount} 元成功")
else:
print("取款失败:金额无效或余额不足")
def get_balance(self):
"""获取余额(公共接口)"""
return self._balance
# 使用
account = BankAccount("123456789", 1000)
account.deposit(500) # 存款 500 元成功
account.withdraw(200) # 取款 200 元成功
print(account.get_balance()) # 1300
print(account._balance) # 1300(可以直接访问,但不推荐)
__ 双下划线(名称修饰)
以 __ 开头的属性会被 Python 名称修饰(name mangling)。
class Example:
def __init__(self):
self.__private = "私有属性"
def __private_method(self):
print("这是一个私有方法")
def public_method(self):
print("这是一个公共方法")
self.__private_method() # 可以调用
# 使用
e = Example()
print(e.__private) # 报错:AttributeError
e.__private_method() # 报错:AttributeError
e.public_method() # 可以调用
继承
继承的概念
继承允许创建一个新类,继承现有类的属性和方法。
基本继承
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print("动物发出声音")
def eat(self):
print("动物在吃东西")
# Dog 类继承 Animal 类
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # 调用父类构造函数
self.breed = breed
def speak(self):
print(f"{self.name} 汪汪叫!")
def fetch(self):
print(f"{self.name} 正在捡球!")
# Cat 类继承 Animal 类
class Cat(Animal):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def speak(self):
print(f"{self.name} 喵喵叫!")
def climb(self):
print(f"{self.name} 正在爬树!")
# 使用
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2, "白色")
dog.speak() # 旺财 汪汪叫!
dog.eat() # 动物在吃东西
dog.fetch() # 旺财 正在捡球!
cat.speak() # 咪咪 喵喵叫!
cat.eat() # 动物在吃东西
cat.climb() # 咪咪 正在爬树!
多重继承
Python 支持多重继承,一个类可以继承多个父类。
class Flyable:
def fly(self):
print("会飞")
class Swimmable:
def swim(self):
print("会游泳")
class Duck(Flyable, Swimmable):
pass
# Duck 类同时拥有 fly 和 swim 方法
duck = Duck()
duck.fly() # 会飞
duck.swim() # 会游泳
super() 函数
super() 用于调用父类的方法。
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 调用父类的 __init__
self.breed = breed
def introduce(self):
super().introduce() # 调用父类方法
print(f"品种:{self.breed}")
class Animal:
def introduce(self):
print(f"我是 {self.name}")
dog = Dog("旺财", "金毛")
dog.introduce()
多态
多态的概念
多态是指同一接口,不同实现。子类可以重写父类的方法,实现不同的行为。
方法重写
class Shape:
def area(self):
print("计算面积")
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
# 使用多态
shapes = [
Rectangle(5, 3),
Circle(4)
]
for shape in shapes:
print(f"面积:{shape.area()}")
接口概念(抽象类)
Python 通过抽象类实现接口概念。
from abc import ABC, abstractmethod
class Animal(ABC):
"""抽象基类"""
@abstractmethod
def speak(self):
"""必须实现的方法"""
pass
@abstractmethod
def move(self):
"""必须实现的方法"""
pass
class Dog(Animal):
def speak(self):
print("汪汪叫")
def move(self):
print("四条腿走路")
class Cat(Animal):
def speak(self):
print("喵喵叫")
def move(self):
print("四肢着地走")
# 可以直接创建 Animal 的实例
animal = Dog()
animal.speak() # 汪汪叫
animal.move() # 四条腿走路
# animal = Animal() # 报错:不能直接实例化抽象类
抽象类
抽象类和抽象方法
抽象类是不能被实例化的类,用于定义接口。
from abc import ABC, abstractmethod
class Vehicle(ABC):
"""交通工具抽象类"""
@abstractmethod
def start(self):
"""启动"""
pass
@abstractmethod
def stop(self):
"""停止"""
pass
def honk(self):
"""鸣笛(具体方法)"""
print("哔哔!")
class Car(Vehicle):
def start(self):
print("汽车启动")
def stop(self):
print("汽车停止")
class Motorcycle(Vehicle):
def start(self):
print("摩托车启动")
def stop(self):
print("摩托车停止")
# 使用
car = Car()
car.start() # 汽车启动
car.honk() # 哔哔!
car.stop() # 汽车停止
motorcycle = Motorcycle()
motorcycle.start() # 摩托车启动
motorcycle.honk() # 哔哔!
motorcycle.stop() # 摩托车停止
# vehicle = Vehicle() # 报错:不能实例化抽象类
抽象属性
from abc import ABC, abstractmethod
class Employee(ABC):
@property
@abstractmethod
def salary(self):
"""抽象属性"""
pass
class FullTimeEmployee(Employee):
@property
def salary(self):
return 10000
class PartTimeEmployee(Employee):
@property
def salary(self):
return 5000
# 使用
ft = FullTimeEmployee()
print(ft.salary) # 10000
pt = PartTimeEmployee()
print(pt.salary) # 5000
实用练习
练习1:银行系统
class BankAccount:
def __init__(self, account_number, balance=0):
self.account_number = account_number
self._balance = balance
def deposit(self, amount):
if amount > 0:
self._balance += amount
print(f"存款 {amount} 成功,余额:{self._balance}")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
if amount > 0 and amount <= self._balance:
self._balance -= amount
print(f"取款 {amount} 成功,余额:{self._balance}")
else:
print("取款失败:金额无效或余额不足")
def get_balance(self):
return self._balance
class SavingsAccount(BankAccount):
def __init__(self, account_number, balance=0, interest_rate=0.03):
super().__init__(account_number, balance)
self.interest_rate = interest_rate
def add_interest(self):
interest = self._balance * self.interest_rate
self._balance += interest
print(f"利息 {interest:.2f} 已添加,余额:{self._balance:.2f}")
class CheckingAccount(BankAccount):
def __init__(self, account_number, balance=0, overdraft_limit=1000):
super().__init__(account_number, balance)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
if amount > 0 and amount <= self._balance + self.overdraft_limit:
self._balance -= amount
print(f"取款 {amount} 成功,余额:{self._balance}")
else:
print(f"取款失败:超过透支限额 {self.overdraft_limit}")
# 使用
savings = SavingsAccount("123456", 1000, 0.05)
savings.deposit(500)
savings.add_interest() # 利息 75.00 已添加
checking = CheckingAccount("789012", 500, 1000)
checking.withdraw(1200) # 超过透支限额
checking.withdraw(600) # 成功
练习2:学生管理系统
class Student:
def __init__(self, student_id, name, age, grade):
self.student_id = student_id
self.name = name
self.age = age
self.grade = grade
def get_info(self):
return f"{self.name}({self.age}岁,{self.grade}年级)"
class UndergraduateStudent(Student):
def __init__(self, student_id, name, age, grade, major):
super().__init__(student_id, name, age, grade)
self.major = major
def get_info(self):
return f"{self.name}({self.age}岁,{self.grade}年级,{self.major}专业)"
class GraduateStudent(Student):
def __init__(self, student_id, name, age, grade, advisor):
super().__init__(student_id, name, age, grade)
self.advisor = advisor
def get_info(self):
return f"{self.name}({self.age}岁,{self.grade}年级,导师:{self.advisor})"
class StudentManager:
def __init__(self):
self.students = {}
def add_student(self, student):
self.students[student.student_id] = student
print(f"已添加学生:{student.get_info()}")
def get_student(self, student_id):
return self.students.get(student_id, None)
def get_all_students(self):
return self.students.values()
# 使用
manager = StudentManager()
undergrad = UndergraduateStudent("001", "张三", 20, "大三", "计算机科学")
grad = GraduateStudent("002", "李四", 25, "研二", "王教授")
manager.add_student(undergrad)
manager.add_student(grad)
for student in manager.get_all_students():
print(student.get_info())
练习3:图形形状系统
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return f"面积:{self.area()}, 周长:{self.perimeter()}"
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
class Triangle(Shape):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
s = (self.a + self.b + self.c) / 2
return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
def perimeter(self):
return self.a + self.b + self.c
# 使用
shapes = [
Rectangle(5, 3),
Circle(4),
Triangle(3, 4, 5)
]
for shape in shapes:
print(shape.describe())
总结
今天我们学习了:
✅ 面向对象编程基础:OOP 的概念和三大特性
✅ 类和对象:类的定义、对象的创建和实例化
✅ 构造函数:__init__ 方法和初始化
✅ 属性和方法:实例属性、类方法、静态方法
✅ 封装:私有属性、Getter 和 Setter
✅ 继承:继承父类、多重继承、super() 函数
✅ 多态:方法重写、抽象类和接口
✅ 抽象类:ABC 基类、抽象方法和属性
重要概念
- 类 vs 对象:类是模板,对象是实例
- self:代表对象实例本身
- 继承:代码复用,建立类之间的关系
- 多态:同一接口,不同实现
- 封装:隐藏内部实现,只暴露必要接口
OOP 设计原则
- 单一职责原则:一个类只做一件事
- 开闭原则:对扩展开放,对修改关闭
- 里氏替换原则:子类可以替换父类
- 接口隔离原则:使用小接口
- 依赖倒置原则:依赖抽象而不是具体实现
下次学习预告
下一篇我们将学习:
- 文件操作进阶(JSON、CSV、Excel处理)
- 装饰器(Decorators)
- 生成器和迭代器
- 常用标准库模块
恭喜你掌握了面向对象编程!你已经能设计复杂的应用程序了!