Python-面向对象编程
·
今日目标:理解 OOP 思想,掌握类与对象、封装、继承、多态,完成愤怒的小鸟案例设计
一、面向过程 vs 面向对象
| 面向过程 | 面向对象(OOP) |
|---|---|
| 按步骤组织代码 | 按对象组织代码 |
| 函数是核心 | 类是核心 |
| 适合简单任务 | 适合复杂系统 |
面向对象三大特性:封装、继承、多态
类比:
- 面向过程:做菜的步骤(洗菜→切菜→炒菜)
- 面向对象:做菜的角色(厨师、锅、食材),每个角色有自己的属性和行为
二、类与对象
2.1 基本概念
- 类(Class):对象的模板/蓝图(如"汽车设计图")
- 对象(Object):类的实例(如"一辆具体的红色 Tesla")
2.2 定义类与创建对象
class Student:
"""学生类"""
def __init__(self, name, age):
"""构造方法,创建对象时自动调用"""
self.name = name # 实例属性
self.age = age
def introduce(self):
"""实例方法"""
print(f"我是{self.name},{self.age}岁")
# 创建对象(实例化)
s1 = Student("张三", 20)
s2 = Student("李四", 22)
s1.introduce() # 我是张三,20岁
s2.introduce() # 我是李四,22岁
2.3 self 是什么?
self 代表当前对象本身。调用方法时 Python 自动把对象传给 self。
s1.introduce() # 等价于 Student.introduce(s1)
2.4 init 构造方法
创建对象时自动调用,用于初始化属性。
2.5 类属性 vs 实例属性
class Dog:
species = "犬科" # 类属性,所有实例共享
def __init__(self, name):
self.name = name # 实例属性,每个对象独有
d1 = Dog("旺财")
d2 = Dog("来福")
print(d1.species, d2.species) # 犬科 犬科
print(d1.name, d2.name) # 旺财 来福
2.6 三种方法
| 类型 | 第一个参数 | 调用方式 | 用途 |
|---|---|---|---|
| 实例方法 | self | 对象.方法() | 操作实例属性 |
| 类方法 | cls | 类.方法() | 操作类属性 |
| 静态方法 | 无 | 类.方法() | 与类相关但不访问属性 |
class MyClass:
count = 0
def instance_method(self):
print("实例方法")
@classmethod
def class_method(cls):
cls.count += 1
@staticmethod
def static_method():
print("静态方法")
2.7 动态添加属性和方法
s = Student("王五", 21)
s.score = 90 # 动态添加属性
print(s.score)
三、封装
封装 = 把数据和对数据的操作包装在一起,隐藏内部细节。
3.1 访问控制约定
| 前缀 | 含义 | 实际效果 |
|---|---|---|
| 无 | 公开 | 可任意访问 |
_name |
受保护(约定) | 仍可访问,但不建议 |
__name |
私有(名称改写) | 外部不可直接访问 |
class BankAccount:
def __init__(self, balance):
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
acc = BankAccount(1000)
acc.deposit(500)
print(acc.get_balance()) # 1500
# print(acc.__balance) # AttributeError
3.2 property 装饰器
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("半径必须为正")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
c = Circle(5)
print(c.area) # 78.54
c.radius = 10 # 通过 setter 修改
四、继承
继承 = 子类自动获得父类的属性和方法。
4.1 单继承
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出声音")
class Dog(Animal):
def speak(self): # 方法重写
print(f"{self.name}:汪汪汪")
class Cat(Animal):
def speak(self):
print(f"{self.name}:喵喵喵")
dog = Dog("旺财")
dog.speak() # 旺财:汪汪汪
4.2 super() 调用父类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, school):
super().__init__(name, age)
self.school = school
s = Student("张三", 20, "清华大学")
print(s.name, s.school)
4.3 多继承(了解)
class A:
def func(self): print("A")
class B:
def func(self): print("B")
class C(A, B):
pass
c = C()
c.func() # A(按 MRO 顺序查找)
五、多态
多态 = 同一方法调用,不同类有不同表现。
def make_sound(animal):
animal.speak() # 不关心具体是什么动物
make_sound(Dog("旺财")) # 汪汪汪
make_sound(Cat("咪咪")) # 喵喵喵
好处:新增子类无需修改调用方代码。
六、案例:愤怒的小鸟(设计思路)
6.1 游戏背景
弹弓发射小鸟,击倒障碍物上的猪。
6.2 类设计
Bird(父类)
├── RedBird(红鸟:普通)
├── YellowBird(黄鸟:加速冲刺)
└── BlueBird(蓝鸟:分裂为三只)
Obstacle(障碍物)
Pig(猪)
Slingshot(弹弓)
Game(游戏主控)
6.3 核心代码框架
class Bird:
def __init__(self, x, y):
self.x, self.y = x, y
def fly(self):
print(f"鸟从({self.x},{self.y})飞出")
class RedBird(Bird):
def fly(self):
print(f"红鸟直线飞行")
class YellowBird(Bird):
def fly(self):
print(f"黄鸟加速冲刺!")
class Pig:
def __init__(self, hp):
self.hp = hp
def hit(self, damage):
self.hp -= damage
if self.hp <= 0:
print("猪被击倒!")
def launch(bird):
bird.fly() # 多态
launch(RedBird(0, 0))
launch(YellowBird(10, 5))
七、练习题
基础题
1. 定义 Rectangle 类,属性 width/height,方法 area() 和 perimeter()。
2. 定义 Book 类,用 property 实现 price 的 getter/setter,价格不能为负。
3. 定义 Vehicle 父类和 Car、Bike 子类,子类重写 move()。
4. 用多态:定义 Shape 父类和 Circle、Rectangle 子类,统一调用 area()。
进阶题
5. 设计 Employee 父类和 Manager 子类,Manager 的 get_salary() 含 20% 奖金。
6. 实现 Stack(栈)类:push、pop、peek、is_empty。
参考答案
点击展开参考答案
class Rectangle:
def __init__(self, w, h):
self.width, self.height = w, h
def area(self): return self.width * self.height
def perimeter(self): return 2 * (self.width + self.height)
class Book:
def __init__(self, title, price):
self.title = title
self._price = price
@property
def price(self): return self._price
@price.setter
def price(self, v):
if v < 0: raise ValueError("价格不能为负")
self._price = v
class Shape:
def area(self): raise NotImplementedError
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return 3.14 * self.r ** 2
class Stack:
def __init__(self): self._data = []
def push(self, item): self._data.append(item)
def pop(self): return self._data.pop() if self._data else None
def peek(self): return self._data[-1] if self._data else None
def is_empty(self): return len(self._data) == 0
更多推荐
所有评论(0)