不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。
python系列之面向对象的三大特性
python系列前期章节
- python系列之注释与变量
- python系列之输入输出语句与数据类型
- python系列之运算符
- python系列之控制流程语句
- python系列之字符串
- python系列之列表
- python系列之元组
- python系列之字典
- python系列之集合
- python系列之函数基础
- python系列之函数进阶
- python系统之综合案例1:用python打造智能诗词生成助手
- python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
- python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
- python系列之类与对象:python系列之详解面向对象的属性)
- python系列之详解面向对象的函数
本文最佳阅读姿势:想象自己是一名建筑大师,正在学习如何用Python构建优雅而坚固的代码大厦!
一、前言:为什么需要面向对象?
想象一下:你要建一座房子。
面向过程的做法:一块砖一块砖地垒,一根梁一根梁地搭,每一步都要亲自指挥。
面向对象的做法:先设计蓝图(类),然后根据蓝图创建房子(对象)。想要新房子?再按蓝图建一个就行!
面向对象编程(OOP)让代码更模块化、更可复用、更易维护。而封装、继承、多态就是OOP的三大基石!
二、封装:给代码穿上"防护服"
2.1 什么是封装?
封装就像自动咖啡机:你只需要按按钮,不需要知道内部如何磨豆、加热、冲泡。
# 没有封装:危险!
class ExposedCoffeeMachine:
def __init__(self):
self.water_temperature = 0 # 公开的水温
self.coffee_beans = 100 # 公开的咖啡豆
machine = ExposedCoffeeMachine()
machine.water_temperature = 1000 # 可以直接调到1000度!危险!
2.2 如何实现封装?
使用单下划线_(约定俗成的保护)和双下划线__(真正的私有化):
class SafeCoffeeMachine:
def __init__(self):
self.__water_temperature = 90 # 私有水温,无法从外部直接访问
self.__coffee_beans = 100 # 私有咖啡豆
self._maintenance_count = 0 # 受保护的维护计数(约定上不直接访问)
# 提供安全的公共方法来访问和修改私有属性
def make_coffee(self):
if self.__coffee_beans >= 10:
self.__coffee_beans -= 10
self._maintenance_count += 1
return "一杯香浓的咖啡☕"
return "咖啡豆不足,请添加!"
def add_beans(self, amount):
if amount > 0:
self.__coffee_beans += amount
return f"添加了{amount}g咖啡豆"
return "请添加正数的咖啡豆"
# 使用安全的咖啡机
machine = SafeCoffeeMachine()
print(machine.make_coffee()) # 一杯香浓的咖啡☕
# print(machine.__coffee_beans) # 报错!无法直接访问私有属性
print(machine.add_beans(50)) # 添加了50g咖啡豆
2.3 @property装饰器:更优雅的封装
class SmartCoffeeMachine:
def __init__(self):
self.__water_temperature = 90
@property
def temperature(self):
"""可以读取温度,但不能直接设置"""
return f"{self.__water_temperature}°C"
@temperature.setter
def temperature(self, value):
"""通过setter方法设置温度,可以进行验证"""
if 80 <= value <= 100:
self.__water_temperature = value
else:
print("温度必须在80-100°C之间!")
machine = SmartCoffeeMachine()
print(machine.temperature) # 90°C
machine.temperature = 120 # 温度必须在80-100°C之间!
machine.temperature = 95 # 设置成功
print(machine.temperature) # 95°C
封装的好处:保护内部数据,简化使用方式,便于内部修改而不影响外部代码。
三、继承:代码的"家族传承"
3.1 什么是继承?
继承就像家族传承:孩子会继承父母的特征,但也可以有自己的特点。
# 父类(基类)
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "某种声音"
def sleep(self):
return f"{self.name}正在睡觉💤"
# 子类(派生类)继承父类
class Dog(Animal): # 括号里写父类名
def speak(self): # 重写父类方法
return "汪汪!🐶"
def fetch(self): # 子类特有方法
return f"{self.name}正在捡球🎾"
class Cat(Animal):
def speak(self):
return "喵喵!🐱"
def climb(self):
return f"{self.name}正在爬树🌳"
# 使用继承
dog = Dog("旺财")
print(dog.sleep()) # 旺财正在睡觉💤 (继承自父类)
print(dog.speak()) # 汪汪!🐶 (子类重写)
print(dog.fetch()) # 旺财正在捡球🎾 (子类特有)
cat = Cat("咪咪")
print(cat.sleep()) # 咪咪正在睡觉💤
print(cat.speak()) # 喵喵!🐱
print(cat.climb()) # 咪咪正在爬树🌳
3.2 super()函数:调用父类方法
class Bird(Animal):
def __init__(self, name, can_fly=True):
super().__init__(name) # 调用父类的__init__方法
self.can_fly = can_fly # 子类新增属性
def speak(self):
return "叽叽!🐦"
def fly(self):
if self.can_fly:
return f"{self.name}正在飞翔🕊️"
return f"{self.name}不会飞😢"
class Penguin(Bird):
def __init__(self, name):
super().__init__(name, can_fly=False) # 企鹅不会飞
penguin = Penguin("企鹅小弟")
print(penguin.fly()) # 企鹅小弟不会飞😢
print(penguin.sleep()) # 企鹅小弟正在睡觉💤
3.3 多重继承:继承多个父类
class Flyable:
def fly(self):
return "在空中飞翔🦅"
class Swimmable:
def swim(self):
return "在水中游泳🐟"
# 鸭子既会飞又会游泳
class Duck(Flyable, Swimmable):
def __init__(self, name):
self.name = name
def speak(self):
return "嘎嘎!🦆"
duck = Duck("唐老鸭")
print(duck.fly()) # 在空中飞翔🦅
print(duck.swim()) # 在水中游泳🐟
继承的好处:代码复用,扩展功能,层次化组织代码。
四、多态:同一方法,不同实现
4.1 什么是多态?
多态就像乐器演奏:不同乐器都有"演奏"方法,但每种乐器的演奏方式不同。
class Instrument:
def play(self):
pass
class Piano(Instrument):
def play(self):
return "钢琴声:叮叮咚咚🎹"
class Guitar(Instrument):
def play(self):
return "吉他声: strumming🎸"
class Drum(Instrument):
def play(self):
return "鼓声: boom boom🥁"
# 多态的魔力:同一方法,不同表现
def perform_concert(instruments):
for instrument in instruments:
print(instrument.play())
# 创建乐队
band = [Piano(), Guitar(), Drum()]
perform_concert(band)
4.2 鸭子类型:Python的特色多态
Python推崇"鸭子类型":如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子。
class Car:
def move(self):
return "汽车在公路上行驶🚗"
class Airplane:
def move(self):
return "飞机在天空中飞行✈️"
class Boat:
def move(self):
return "船在水面上航行⛵"
# 这些类没有共同的父类,但它们都有move方法
def travel(vehicle):
print(vehicle.move())
# 都可以调用move方法,这就是鸭子类型
travel(Car()) # 汽车在公路上行驶🚗
travel(Airplane()) # 飞机在天空中飞行✈️
travel(Boat()) # 船在水面上航行⛵
4.3 抽象基类:强制子类实现方法
from abc import ABC, abstractmethod
# 抽象基类
class Shape(ABC):
@abstractmethod
def area(self):
"""计算面积,子类必须实现"""
pass
@abstractmethod
def perimeter(self):
"""计算周长,子类必须实现"""
pass
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 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)
# 使用
shapes = [Circle(5), Rectangle(4, 6)]
for shape in shapes:
print(f"面积: {shape.area()}, 周长: {shape.perimeter()}")
多态的好处:提高代码灵活性,接口统一,易于扩展。
五、综合实战:动物园管理系统
让我们用三大特性构建一个完整的系统:
from abc import ABC, abstractmethod
from datetime import datetime
# 抽象基类
class Animal(ABC):
def __init__(self, name, age):
self.name = name
self.age = age
self.__id = datetime.now().strftime("%Y%m%d%H%M%S") # 封装:私有ID
@property
def id(self): # 封装:只读属性
return self.__id
@abstractmethod
def speak(self):
pass
def eat(self, food):
return f"{self.name}正在吃{food}"
def sleep(self):
return f"{self.name}正在睡觉💤"
# 哺乳动物继承层次
class Mammal(Animal):
def __init__(self, name, age, fur_color):
super().__init__(name, age)
self.fur_color = fur_color # 哺乳动物特有属性
def give_birth(self):
return f"{self.name}正在生宝宝👶"
# 鸟类继承层次
class Bird(Animal):
def __init__(self, name, age, wingspan):
super().__init__(name, age)
self.wingspan = wingspan # 鸟类特有属性
def fly(self):
return f"{self.name}正在展翅飞翔🕊️"
# 具体的动物类
class Lion(Mammal):
def speak(self): # 多态:同一方法不同实现
return " roar!🦁"
def hunt(self):
return f"{self.name}正在狩猎🐾"
class Elephant(Mammal):
def speak(self):
return " trumpet!🐘"
def spray_water(self):
return f"{self.name}正在用鼻子喷水💦"
class Eagle(Bird):
def speak(self):
return " screech!🦅"
def hunt(self): # 与Lion类的hunt方法同名但实现不同
return f"{self.name}正在高空寻找猎物👀"
# 动物园管理类
class Zoo:
def __init__(self, name):
self.name = name
self.__animals = [] # 封装:私有列表
def add_animal(self, animal):
self.__animals.append(animal)
print(f"添加了{animal.name}到动物园")
def show_animals(self):
print(f"\n=== {self.name}的动物们 ===")
for animal in self.__animals:
print(f"{animal.name} ({type(animal).__name__}): {animal.speak()}")
def daily_routine(self):
print(f"\n=== {self.name}的日常活动 ===")
for animal in self.__animals:
# 多态:不同对象调用同一方法有不同的行为
print(animal.eat("食物"))
print(animal.sleep())
if isinstance(animal, Bird):
print(animal.fly()) # 只有鸟类会飞
elif isinstance(animal, Lion):
print(animal.hunt()) # 只有狮子会狩猎
使用动物园系统
zoo = Zoo("神奇动物园")
# 添加各种动物(继承自不同父类)
```python
zoo.add_animal(Lion("辛巴", 5, "金色"))
zoo.add_animal(Elephant("笨笨", 10, "灰色"))
zoo.add_animal(Eagle("闪电", 3, 2.5))
展示动物信息
zoo.show_animals()
进行日常活动
zoo.daily_routine()
访问封装属性
print(f"\n狮子ID: {zoo._Zoo__animals[0].id}") # 可以访问但一般不这样做
六、总结:三大特性的关系
| 特性 | 比喻 | 作用 | 关键语法 |
|---|---|---|---|
| 封装 | 自动咖啡机 | 隐藏实现细节,保护数据 | __私有属性, @property |
| 继承 | 家族传承 | 代码复用,扩展功能 | class Child(Parent):, super() |
| 多态 | 乐器演奏 | 同一接口,不同实现 | 方法重写,鸭子类型 |
三者关系:
- 封装是基础:保护对象内部状态
- 继承是扩展:建立类之间的关系层次
- 多态是表现:基于继承实现同一方法的不同行为
七、最佳实践与常见误区
7.1 最佳实践
- 优先使用组合而非继承:除非确实是"is-a"关系,否则使用组合
- 保持类的单一职责:一个类只做一件事
- 适度使用继承:避免过深的继承层次
- 利用多态提高灵活性:针对接口编程,而不是实现编程
7.2 常见误区
- 过度封装:不是所有属性都需要私有化
- 滥用继承:不要为了代码复用而使用继承
- 忽视鸭子类型:不要过度设计复杂的类层次
八、练习挑战
- 为上面的动物园添加新的动物类型(如鱼类)
- 实现一个
Zookeeper类,负责照顾动物 - 为动物添加
feed方法,但不同动物吃不同食物(体现多态) - 使用
@property为动物添加年龄验证(不能为负数)
记住:封装、继承、多态不是独立的,而是相互协作的三大支柱。用好它们,你就能构建出优雅、健壮、易维护的Python程序!

被折叠的 条评论
为什么被折叠?



