一、什么是面向对象?
面向过程:关注 "怎么做" → 一步步执行
面向对象:关注 "谁来做" → 找到对象,让对象去执行
现实世界的映射:
┌─────────────────────────────────────────────┐
│ 现实世界 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. isinstance 和 issubclass
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岁) ← 对象(具体个体)
三大特性:
封装 → 把东西包起来,只暴露接口
继承 → 儿子继承老爸,代码复用
多态 → 同一方法,不同表现
💡 你现在只要记住:类 = 图纸,对象 = 实物,这俩搞懂就入门了!

微信打赏
Comments | Nothing