python系列之面向对象的三大特性

不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。

python系列前期章节

  1. python系列之注释与变量
  2. python系列之输入输出语句与数据类型
  3. python系列之运算符
  4. python系列之控制流程语句
  5. python系列之字符串
  6. python系列之列表
  7. python系列之元组
  8. python系列之字典
  9. python系列之集合
  10. python系列之函数基础
  11. python系列之函数进阶
  12. python系统之综合案例1:用python打造智能诗词生成助手
  13. python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
  14. python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
  15. python系列之类与对象:python系列之详解面向对象的属性)
  16. 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 最佳实践

  1. 优先使用组合而非继承:除非确实是"is-a"关系,否则使用组合
  2. 保持类的单一职责:一个类只做一件事
  3. 适度使用继承:避免过深的继承层次
  4. 利用多态提高灵活性:针对接口编程,而不是实现编程

7.2 常见误区

  1. 过度封装:不是所有属性都需要私有化
  2. 滥用继承:不要为了代码复用而使用继承
  3. 忽视鸭子类型:不要过度设计复杂的类层次

八、练习挑战

  1. 为上面的动物园添加新的动物类型(如鱼类)
  2. 实现一个Zookeeper类,负责照顾动物
  3. 为动物添加feed方法,但不同动物吃不同食物(体现多态)
  4. 使用@property为动物添加年龄验证(不能为负数)

记住:封装、继承、多态不是独立的,而是相互协作的三大支柱。用好它们,你就能构建出优雅、健壮、易维护的Python程序!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值