一、什么是面向对象?

面向过程:关注 "怎么做" → 一步步执行
面向对象:关注 "谁来做" → 找到对象,让对象去执行
现实世界的映射:
┌─────────────────────────────────────────────┐
│  现实世界          Python                      │
│  ──────────       ──────────                  │
│  一类事物    →     class(类)                 │
│  具体个体    →     object(对象/实例)          │
│  特征/属性   →     attribute(属性)            │
│  行为/能力   →     method(方法)              │
└─────────────────────────────────────────────┘

二、类和对象的基础

1. 定义类和创建对象

# 定义一个 "猫" 类
class Cat:
    # 类属性(所有猫共享)
    species = "猫科动物"

    # 初始化方法(构造函数)—— 创建对象时自动调用
    def __init__(self, name, age, color):
        # 实例属性(每只猫独有的)
        self.name = name      # 名字
        self.age = age        # 年龄
        self.color = color    # 颜色

    # 实例方法
    def meow(self):
        print(f"{self.name} 说:喵喵喵~")

    def info(self):
        print(f"名字:{self.name},年龄:{self.age},颜色:{self.color}")


# ======= 创建对象(实例化) =======
cat1 = Cat("咪咪", 2, "白色")
cat2 = Cat("黑炭", 3, "黑色")

cat1.meow()   # 咪咪 说:喵喵喵~
cat2.info()   # 名字:黑炭,年龄:3,颜色:黑色

print(cat1.species)  # 猫科动物
print(cat2.species)  # 猫科动物

2. self 是什么?

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

    def bark(self):
        # self 就是调用这个方法的对象本身
        print(f"{self.name} 在叫:汪汪!")

dog = Dog("旺财")
dog.bark()        # 等价于 Dog.bark(dog) → self 就是 dog

dog2 = Dog("来福")
dog2.bark()       # self 就是 dog2
self 的本质:
┌──────────────────────────────────────┐
│  dog.bark()  等价于  Dog.bark(dog)    │
│                                      │
│  self = 调用方法的那个对象             │
│  谁调用,self 就是谁                   │
└──────────────────────────────────────┘

三、实例属性 vs 类属性

class Student:
    # 类属性:所有对象共享
    school = "清华大学"
    count = 0

    def __init__(self, name, score):
        # 实例属性:每个对象独有
        self.name = name
        self.score = score
        Student.count += 1  # 每创建一个学生,计数+1


s1 = Student("张三", 90)
s2 = Student("李四", 85)

# 实例属性:各自独立
print(s1.name)    # 张三
print(s2.name)    # 李四

# 类属性:共同分享
print(s1.school)  # 清华大学
print(s2.school)  # 清华大学
print(Student.count)  # 2
┌─────────────────────────────────────────────┐
│  类属性  → 属于类     → 所有对象共享         │
│  实例属性 → 属于对象   → 每个对象独有         │
└─────────────────────────────────────────────┘

四、三大核心特性

🔒 1. 封装(Encapsulation)

把属性和方法包装在一起,隐藏内部细节

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner           # 公开属性
        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 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"取出 {amount},余额:{self.__balance}")
        else:
            print("余额不足或金额无效")

    def get_balance(self):
        return self.__balance


acc = BankAccount("张三", 1000)
acc.deposit(500)         # 存入 500,余额:1500
acc.withdraw(200)        # 取出 200,余额:1300
print(acc.get_balance()) # 1300

# acc.__balance = -9999  ❌ 报错!无法直接修改(保护了数据安全)
# 私有属性仍可通过 _类名__属性名 访问(不推荐)
print(acc._BankAccount__balance)  # 1300
访问权限:
┌────────────┬───────────┬─────────────────────┐
│   写法      │   级别     │   说明               │
├────────────┼───────────┼─────────────────────┤
│  name      │   公开     │  任何地方都能访问      │
│  _name     │   保护     │  建议不要外部访问      │
│  __name    │   私有     │  只有类内部能访问      │
└────────────┴───────────┴─────────────────────┘

@property 装饰器(更优雅的封装)

class Circle:
    def __init__(self, radius):
        self.__radius = radius

    # 把方法变成属性一样访问
    @property
    def radius(self):
        """getter:读取时调用"""
        return self.__radius

    @radius.setter
    def radius(self, value):
        """setter:赋值时调用"""
        if value > 0:
            self.__radius = value
        else:
            print("半径必须大于0!")

    @property
    def area(self):
        """只读属性(没有 setter)"""
        return 3.14159 * self.__radius ** 2


c = Circle(5)
print(c.radius)    # 5       (像属性一样读取)
print(c.area)      # 78.54   (计算属性)

c.radius = 10      # 像属性一样赋值 → 实际调用 setter
print(c.area)      # 314.16

# c.area = 100     ❌ 只读,不能赋值
# c.radius = -3    ❌ radius must be > 0

🧬 2. 继承(Inheritance)

子类继承父类的属性和方法,实现代码复用

# ========== 父类(基类)==========
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print(f"{self.name} 在吃东西")

    def sleep(self):
        print(f"{self.name} 在睡觉")


# ========== 子类(派生类)==========
class Dog(Animal):       # 继承 Animal
    def __init__(self, name, age, breed):
        super().__init__(name, age)  # 调用父类的 __init__
        self.breed = breed           # 子类独有的属性

    def bark(self):                  # 子类独有的方法
        print(f"{self.name} 汪汪叫!")


class Cat(Animal):       # 继承 Animal
    def meow(self):
        print(f"{self.name} 喵喵叫!")


# 使用
dog = Dog("旺财", 3, "金毛")
dog.eat()       # 继承的方法 ✅ 旺财 在吃东西
dog.sleep()     # 继承的方法 ✅ 旺财 在睡觉
dog.bark()      # 自己的方法 ✅ 旺财 汪汪叫!

cat = Cat("咪咪", 2)
cat.eat()       # 继承的方法 ✅ 咪咪 在吃东西
cat.meow()      # 自己的方法 ✅ 咪咪 喵喵叫!
# cat.bark()    # ❌ 报错!Cat 没有 bark 方法
继承关系:
        Animal
       /      
    Dog        Cat
   (bark)     (meow)

子类自动拥有父类的属性和方法

方法重写(Override)

class Animal:
    def speak(self):
        print("动物发出声音")


class Dog(Animal):
    # 重写父类的 speak 方法
    def speak(self):
        print("汪汪汪!")


class Cat(Animal):
    def speak(self):
        print("喵喵喵!")


dog = Dog()
cat = Cat()
dog.speak()  # 汪汪汪!  ← 调用的是自己的(重写后的)
cat.speak()  # 喵喵喵!

多重继承

class Flyable:
    def fly(self):
        print("我会飞!")

class Swimmable:
    def swim(self):
        print("我会游泳!")

class Duck(Flyable, Swimmable):   # 同时继承两个类
    def quack(self):
        print("嘎嘎嘎!")


duck = Duck()
duck.fly()    # ✅ 我会飞!
duck.swim()   # ✅ 我会游泳!
duck.quack()  # ✅ 嘎嘎嘎!
多重继承查找顺序(MRO):
Duck → Flyable → Swimmable → object

🎭 3. 多态(Polymorphism)

同一个方法,不同对象有不同的行为

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "汪汪汪!"

class Cat(Animal):
    def speak(self):
        return "喵喵喵!"

class Duck(Animal):
    def speak(self):
        return "嘎嘎嘎!"


# ====== 多态的威力 ======
def animal_concert(animal):    # 不关心具体类型
    print(animal.speak())      # 同一个方法名,不同行为


# 同一个函数,传入不同对象,产生不同结果
animal_concert(Dog())    # 汪汪汪!
animal_concert(Cat())    # 喵喵喵!
animal_concert(Duck())   # 嘎嘎嘎!
# Python 的鸭子类型:不看类型,看能力
class Car:
    def speak(self):
        return "滴滴滴!"

# Car 不是 Animal 的子类,但有 speak 方法,照样能用!
animal_concert(Car())    # 滴滴滴!

# "如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"

五、其他重要特性

1. __str____repr__(对象的字符串表示)

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

    # print() 时调用 → 面向用户
    def __str__(self):
        return f"学生:{self.name},{self.age}岁"

    # 交互式环境显示 → 面向开发者
    def __repr__(self):
        return f"Student('{self.name}', {self.age})"


s = Student("张三", 20)
print(s)       # 学生:张三,20岁
repr(s)        # Student('张三', 20)

2. 魔术方法(Dunder Methods)

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):          # 重载 + 号
        return Vector(self.x + other.x, self.y + other.y)

    def __sub__(self, other):          # 重载 - 号
        return Vector(self.x - other.x, self.y - other.y)

    def __mul__(self, scalar):         # 重载 * 号
        return Vector(self.x * scalar, self.y * scalar)

    def __len__(self):                 # 支持 len()
        return int((self.x**2 + self.y**2) ** 0.5)

    def __eq__(self, other):           # 重载 == 号
        return self.x == other.x and self.y == other.y

    def __str__(self):
        return f"Vector({self.x}, {self.y})"


v1 = Vector(3, 4)
v2 = Vector(1, 2)

print(v1 + v2)     # Vector(4, 6)
print(v1 - v2)     # Vector(2, 2)
print(v1 * 3)      # Vector(9, 12)
print(len(v1))     # 5
print(v1 == v2)    # False
常用魔术方法:
┌──────────────┬──────────────────┐
│   方法        │   触发方式        │
├──────────────┼──────────────────┤
│ __init__     │  对象创建时       │
│ __str__      │  print(obj)      │
│ __repr__     │  repr(obj)       │
│ __add__      │  obj1 + obj2     │
│ __len__      │  len(obj)        │
│ __eq__       │  obj1 == obj2    │
│ __getitem__  │  obj[key]        │
│ __call__     │  obj()           │
│ __del__      │  对象销毁时       │
└──────────────┴──────────────────┘

3. 类方法和静态方法

class MathHelper:
    pi = 3.14159

    # 实例方法:操作实例属性,第一个参数是 self
    def instance_method(self):
        print(f"我是实例方法,self={self}")

    # 类方法:操作类属性,第一个参数是 cls(类本身)
    @classmethod
    def class_method(cls):
        print(f"我是类方法,cls={cls}")
        print(f"pi = {cls.pi}")

    # 静态方法:跟类/实例都无关的工具函数
    @staticmethod
    def static_method(a, b):
        print(f"我是静态方法:{a} + {b} = {a + b}")


m = MathHelper()
m.instance_method()     # 需要对象
MathHelper.class_method()    # 通过类调用
MathHelper.static_method(3, 5)  # 通过类调用
┌──────────────┬────────────┬─────────────────────────┐
│   类型        │  第一个参数  │   用途                   │
├──────────────┼────────────┼─────────────────────────┤
│ 实例方法      │  self      │  操作实例属性             │
│ 类方法@cls    │  cls       │  操作类属性,工厂方法      │
│ 静态方法@stat │  无        │  独立的工具函数            │
└──────────────┴────────────┴─────────────────────────┘

4. isinstanceissubclass

class Animal: pass
class Dog(Animal): pass
class Cat(Animal): pass

dog = Dog()

print(isinstance(dog, Dog))       # True  ← dog 是 Dog 的实例吗?
print(isinstance(dog, Animal))    # True  ← dog 是 Animal 的实例吗?
print(isinstance(dog, Cat))       # False

print(issubclass(Dog, Animal))    # True  ← Dog 是 Animal 的子类吗?
print(issubclass(Cat, Dog))       # False

六、综合实战案例

🎮 案例:银行账户管理系统

class Account:
    """银行账户类"""
    bank_name = "中国Python银行"    # 类属性
    _total_accounts = 0

    def __init__(self, owner, balance=0):
        self.owner = owner
        self.__balance = balance
        self.__transactions = []      # 交易记录
        Account._total_accounts += 1

    @property
    def balance(self):
        return self.__balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("存款金额必须大于0")
        self.__balance += amount
        self.__transactions.append(f"存入 +{amount}")
        print(f"✅ 存入 {amount} 元,余额:{self.__balance} 元")

    def withdraw(self, amount):
        if amount <= 0:
            raise ValueError("取款金额必须大于0")
        if amount > self.__balance:
            print("❌ 余额不足!")
            return
        self.__balance -= amount
        self.__transactions.append(f"取出 -{amount}")
        print(f"✅ 取出 {amount} 元,余额:{self.__balance} 元")

    def transfer(self, other, amount):
        """转账"""
        if amount > self.__balance:
            print("❌ 余额不足,转账失败")
            return
        self.withdraw(amount)
        other.deposit(amount)
        print(f"✅ 成功向 {other.owner} 转账 {amount} 元")

    def show_transactions(self):
        print(f"n{'='*30}")
        print(f"  {self.owner} 的交易记录")
        print(f"{'='*30}")
        for t in self.__transactions:
            print(f"  {t}")
        print(f"  当前余额:{self.__balance}")
        print(f"{'='*30}")

    def __str__(self):
        return f"账户({self.owner}, 余额:{self.__balance})"

    @classmethod
    def get_bank_info(cls):
        return f"银行:{cls.bank_name},总账户数:{cls._total_accounts}"


# ===== 使用 =====
acc1 = Account("张三", 10000)
acc2 = Account("李四", 5000)

acc1.deposit(3000)        # ✅ 存入 3000 元,余额:13000 元
acc1.withdraw(2000)       # ✅ 取出 2000 元,余额:11000 元
acc1.transfer(acc2, 5000) # ✅ 成功向 李四 转账 5000 元

acc1.show_transactions()
acc2.show_transactions()

print(Account.get_bank_info())
# 银行:中国Python银行,总账户数:2

七、总结速查表

┌─────────────────────────────────────────────────────┐
│                  Python 面向对象                      │
├─────────────┬───────────────────────────────────────┤
│  基础概念     │  class → 定义类                       │
│             │  obj = ClassName() → 创建对象           │
│             │  self → 代表对象本身                     │
├─────────────┼───────────────────────────────────────┤
│  属性        │  实例属性 → 每个对象独有                │
│             │  类属性   → 所有对象共享                 │
├─────────────┼───────────────────────────────────────┤
│  方法        │  实例方法 → def method(self)           │
│             │  类方法   → @classmethod               │
│             │  静态方法 → @staticmethod              │
│             │  @property → 把方法变成属性              │
├─────────────┼───────────────────────────────────────┤
│  三大特性     │  封装 → 隐藏内部细节,提供接口          │
│             │  继承 → 子类复用父类代码                 │
│             │  多态 → 同一方法,不同表现               │
├─────────────┼───────────────────────────────────────┤
│  访问控制     │  name   → 公开                       │
│             │  _name  → 保护                        │
│             │  __name → 私有                        │
├─────────────┼───────────────────────────────────────┤
│  魔术方法     │  __init__  → 初始化                   │
│             │  __str__   → print显示                 │
│             │  __add__   → +运算                    │
│             │  __len__   → len()                    │
└─────────────┴───────────────────────────────────────┘

💡 学习建议:先掌握 class + __init__ + self + 继承,再逐步学习封装、多态和魔术方法。多写多练,面向对象就会越来越顺!

面向对象编程(OOP)—— 通俗版

一句话理解

面向对象 = 用"类"来描述一类事物,用"对象"来代表具体个体


生活中的例子 🐱

你去宠物店:

"猫" 这个概念          →  类(class)    = 模板/图纸
这只叫"咪咪"的白猫      →  对象(object) = 根据模板造出来的东西
咪咪的名字、年龄        →  属性(attribute)
咪咪会叫、会跑          →  方法(method)

类 = 图纸,对象 = 用图纸造出来的实物


代码演示(超简单版)

# ========== 第1步:定义类(画图纸)==========
class Cat:
    def __init__(self, name, age):    # 初始化:每只猫都要有名字和年龄
        self.name = name              # 属性:名字
        self.age = age                # 属性:年龄

    def meow(self):                   # 方法:猫会叫
        print(f"{self.name}:喵喵喵~")

    def info(self):                   # 方法:介绍自己
        print(f"我是{self.name},{self.age}岁了")


# ========== 第2步:创建对象(造猫)==========
cat1 = Cat("咪咪", 2)     # 造一只叫咪咪的猫
cat2 = Cat("黑炭", 3)     # 造一只叫黑炭的猫


# ========== 第3步:使用对象 ==========
cat1.meow()               # 咪咪:喵喵喵~
cat2.info()               # 我是黑炭,3岁了
print(cat1.name)          # 咪咪

就这么简单!3步:定义类 → 创建对象 → 使用对象


面向对象的 3 大特性(大白话)

1️⃣ 封装 —— 把东西包起来

class Phone:
    def __init__(self):
        self.__password = "1234"     # 私有:别人看不到密码

    def unlock(self, pwd):           # 提供接口
        if pwd == self.__password:
            print("解锁成功 ✅")
        else:
            print("密码错误 ❌")

p = Phone()
p.unlock("1234")           # 解锁成功 ✅
# p.__password              报错!看不到密码

封装 = 藏好内部细节,只给你用的接口
就像你用手机,不需要知道里面电路怎么走


2️⃣ 继承 —— 儿子继承老爸

# 老爸:动物
class Animal:
    def eat(self):
        print("吃东西")

# 儿子:狗(继承动物)
class Dog(Animal):          # 括号里写老爸
    def bark(self):
        print("汪汪汪!")

# 儿子:猫
class Cat(Animal):
    def meow(self):
        print("喵喵喵!")

dog = Dog()
dog.eat()       # ✅ 吃东西     ← 继承来的
dog.bark()      # ✅ 汪汪汪!   ← 自己的

cat = Cat()
cat.eat()       # ✅ 吃东西     ← 继承来的
cat.meow()      # ✅ 喵喵喵!   ← 自己的

继承 = 儿子自动拥有老爸的能力,不用重复写代码


3️⃣ 多态 —— 同一件事,不同人做不一样

class Dog:
    def speak(self):
        return "汪汪汪!"

class Cat:
    def speak(self):
        return "喵喵喵!"

class Duck:
    def speak(self):
        return "嘎嘎嘎!"

# 同一个函数,传不同对象,结果不同
def make_sound(animal):
    print(animal.speak())

make_sound(Dog())     # 汪汪汪!
make_sound(Cat())     # 喵喵喵!
make_sound(Duck())    # 嘎嘎嘎!

多态 = 同一个方法名,不同对象表现不同


为什么用面向对象?

不用面向对象(面向过程):
  → 代码一长就乱,数据和函数分散各处

用面向对象:
  → 把相关数据和功能打包在一起,像乐高积木一样好组装

简单说:
  ✅ 代码更清晰(一个类管一件事)
  ✅ 代码可复用(继承)
  ✅ 好维护好扩展

一张图总结

        ┌─────────────────────────────────┐
        │          class Cat              │  ← 类(模板)
        │  ┌───────────────────────────┐  │
        │  │ 属性:name, age           │  │  ← 特征
        │  │ 方法:meow(), info()      │  │  ← 行为
        │  └───────────────────────────┘  │
        └─────────────────────────────────┘
                    │
           创建多个对象(实例)
                ┌───┴───┐
                ▼       ▼
            咪咪(2岁)  黑炭(3岁)      ← 对象(具体个体)
三大特性:
  封装 → 把东西包起来,只暴露接口
  继承 → 儿子继承老爸,代码复用
  多态 → 同一方法,不同表现

💡 你现在只要记住:类 = 图纸,对象 = 实物,这俩搞懂就入门了!

转载请注明原文链接:首页 > 日常 > Python 面向对象编程 (OOP) 完全教程
  • 微信打赏微信打赏

AnHui.HuaiNan

我很感谢那些爱过我的人.