前面我们写的函数,都是"一堆散装的动作"。但真实世界不是这么组织的——真实世界里是一个个对象:一只猫、一辆车、一个账户。

对象有自己的数据(猫的颜色、车的速度),也有自己的行为(猫会叫、车会跑)。

面向对象编程(OOP),就是让代码也用这种"对象"的方式组织。这是从"写脚本"到"写程序"的分水岭。


一、类(class):对象的"图纸"

class 是创建对象的模板,就像"猫"这个物种的图纸。先定义图纸,再造出具体的猫:

class Cat:
    def __init__(self, name, color):     # 构造方法:造猫时自动执行
        self.name = name                 # 把数据挂到对象上
        self.color = color

    def meow(self):                      # 方法:对象的行为
        print(f"{self.name} 喵喵叫")
  • class Cat: 定义了一个叫 Cat 的类。
  • __init__构造方法,造对象时自动跑,用来初始化数据。
  • self 代表"这个对象自己",self.name 就是"这个对象的 name"。
🧊 冷笑话:"Python 为什么要去上学?""为了提升它的 class(类 / 班级)。"——class 在 Python 里是"类",英文里又是"班级",一举两得。

二、造对象、用对象

cat1 = Cat("小黑", "黑色")    # 造一只叫小黑的猫
cat2 = Cat("小白", "白色")    # 再造一只

print(cat1.name)             # 小黑
print(cat2.color)            # 白色

cat1.meow()                  # 小黑 喵喵叫
cat2.meow()                  # 小白 喵喵叫

同一个类,可以造出无数个对象,每个对象的数据各自独立。


三、self 到底是谁?

self 不是关键字,只是一个约定俗成的名字,代表"调用方法的那个对象"。cat1.meow() 时,self 就是 cat1cat2.meow() 时,self 就是 cat2

所以 self.name 才能分别拿到"小黑"和"小白"。


四、一个更实用的例子:银行账户

class Account:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):          # 存钱
        self.balance += amount
        print(f"存入 {amount},余额 {self.balance}")

    def withdraw(self, amount):         # 取钱
        if amount > self.balance:
            print("余额不足")
        else:
            self.balance -= amount
            print(f"取出 {amount},余额 {self.balance}")

acc = Account("张三", 1000)
acc.deposit(500)      # 存入 500,余额 1500
acc.withdraw(200)     # 取出 200,余额 1300
acc.withdraw(9999)    # 余额不足

数据(余额)和行为(存/取)被"打包"进了同一个对象,逻辑清晰多了。


五、继承:子类复用父类

继承让一个类"继承"另一个类的数据和方法,避免重复:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        print(f"{self.name} 发出了声音")

class Dog(Animal):            # Dog 继承 Animal
    def speak(self):          # 覆盖(重写)父类的方法
        print(f"{self.name} 汪汪叫")

class Cat(Animal):
    def speak(self):
        print(f"{self.name} 喵喵叫")

dog = Dog("旺财")
dog.speak()                   # 旺财 汪汪叫
  • class Dog(Animal):Dog 继承 Animal,自动拥有 __init__ 里的 self.name
  • 子类可以重写父类方法(speak 各自不同)。

继承的精髓:把公共的东西放父类,子类只写差异部分。


六、封装:把数据藏起来

面向对象强调"数据不应该被随便改"。Python 用下划线约定"这是私有属性,别碰":

class Account:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = balance      # 下划线开头:约定"私有"

    def get_balance(self):
        return self._balance         # 通过方法访问,而不是直接摸

    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
Python 的"私有"是约定而非强制(不像 Java),靠自觉和规范,而不是靠编译器拦你。

七、什么时候用类?什么时候用函数?

  • 函数:一个独立的小动作,输入→输出。适合"算个平方""读个文件"。
  • :有"数据 + 操作数据的行为",且这些要打包在一起、可能要多个实例。适合"账户""用户""游戏角色"。

简单场景别硬上类,函数就够;数据和行为紧密耦合时,用类更清晰。


八、动手时间 🎯

实验 1:学生类

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def grade(self):
        if self.score >= 90:
            return "A"
        elif self.score >= 70:
            return "B"
        elif self.score >= 60:
            return "C"
        return "D"

s = Student("张三", 85)
print(s.name, s.grade())    # 张三 B

实验 2:继承实战——形状求面积

class Shape:
    def area(self):
        return 0

class Circle(Shape):
    def __init__(self, r):
        self.r = r
    def area(self):
        return 3.14 * self.r * self.r

class Rectangle(Shape):
    def __init__(self, w, h):
        self.w = w
        self.h = h
    def area(self):
        return self.w * self.h

print(Circle(5).area())       # 78.5
print(Rectangle(3, 4).area()) # 12

实验 3:待办事项类

class TodoList:
    def __init__(self):
        self.items = []

    def add(self, item):
        self.items.append(item)
        print(f"已添加:{item}")

    def done(self, index):
        removed = self.items.pop(index)
        print(f"已完成:{removed}")

    def show(self):
        for i, item in enumerate(self.items):
            print(f"{i}. {item}")

todo = TodoList()
todo.add("学 Python")
todo.add("写作业")
todo.show()
todo.done(0)

九、小结

  1. class 是图纸,对象是造出来的实例__init__ 初始化数据,self 代表对象自己。
  2. 方法 = 打包在类里的函数,把"数据 + 行为"捆在一起,逻辑更清晰。
  3. 继承复用公共代码、重写体现差异;下划线开头是"私有"约定;简单场景别硬上类。

下一课,我们学 进阶语法与函数式编程——生成器、装饰器、map/filter,这些是读懂高手代码、写出优雅代码的钥匙。

先把「银行账户」和「形状求面积」敲熟,面向对象的手感就长在你脑子里了。

标签: none

添加新评论