Python面向对象:class类与对象,3个案例讲透封装与继承
前面的代码都是"写一堆函数 + 操作数据"。但当程序变大,这种方式会变得很难管理。面向对象编程(OOP)用"把数据和操作打包"的方式,让代码更好组织。这篇文章用3个案例讲清楚类和对象的核心概念。
一句话概括
这篇文章解决一个问题:学会用 class 定义类,理解封装和继承两个核心概念。
类和对象是什么
类(Class) :抽象的模板,比如"人"这个概念
对象(Object):具体的实例,比如"小明"这个具体的人
python
# 定义一个"学生"类
class Student:
# __init__ 是构造函数,创建对象时自动调用
def __init__(self, name, score):
self.name = name # 实例属性
self.score = score # 实例属性
def say_hello(self): # 实例方法
print(f"大家好,我叫{self.name}!")
def get_grade(self): # 实例方法
if self.score >= 90:
return "A"
elif self.score >= 80:
return "B"
else:
return "C"
# 创建对象(实例化)
s1 = Student("小明", 95)
s2 = Student("小红", 87)
# 调用对象的方法
s1.say_hello() # 大家好,我叫小明!
print(s1.get_grade()) # A
print(s2.get_grade()) # B
init:构造函数
__init__ 在创建对象时自动调用,用来初始化对象的属性:
python
class Person:
def __init__(self, name, age):
self.name = name # 把name存到对象里
self.age = age # 把age存到对象里
print(f"{self.name}出生了!")
def introduce(self):
print(f"我叫{self.name},今年{self.age}岁。")
p = Person("小明", 18) # 输出:小明出生了!
p.introduce() # 输出:我叫小明,今年18岁。
self 是什么
self 是指当前对象本身 ,类似于其他语言里的 this。
python
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
# self.name 指的是这个对象自己的name
print(f"{self.name}: 汪汪汪!")
dog1 = Dog("旺财")
dog2 = Dog("小白")
dog1.bark() # 旺财: 汪汪汪!
dog2.bark() # 小白: 汪汪汪!
案例1:银行账户系统
python
class BankAccount:
"""银行账户类"""
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
print(f"为 {owner} 开户,初始余额:{balance}")
def deposit(self, amount):
"""存款"""
if amount > 0:
self.balance += amount
print(f"存款 {amount},余额 {self.balance}")
else:
print("存款金额必须为正!")
def withdraw(self, amount):
"""取款"""
if amount > self.balance:
print(f"余额不足!当前余额:{self.balance}")
elif amount <= 0:
print("取款金额必须为正!")
else:
self.balance -= amount
print(f"取款 {amount},余额 {self.balance}")
def show_balance(self):
"""显示余额"""
print(f"{self.owner} 的余额:{self.balance}")
# 测试
account = BankAccount("小明", 1000)
account.deposit(500) # 存款 500,余额 1500
account.withdraw(200) # 取款 200,余额 1300
account.withdraw(2000) # 余额不足!当前余额:1300
account.show_balance() # 小明 的余额:1300
继承:复用类
继承允许我们基于已有的类创建新类,新类自动拥有父类的属性和方法。
python
# 父类
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现speak方法")
# 子类:狗
class Dog(Animal):
def speak(self):
return f"{self.name}: 汪汪汪!"
# 子类:猫
class Cat(Animal):
def speak(self):
return f"{self.name}: 喵喵喵!"
# 子类:鸭子
class Duck(Animal):
def speak(self):
return f"{self.name}: 嘎嘎嘎!"
# 测试
animals = [Dog("旺财"), Cat("小白"), Duck("唐老鸭")]
for animal in animals:
print(animal.speak())
输出:
旺财: 汪汪汪!
小白: 喵喵喵!
唐老鸭: 嘎嘎嘎!
案例2:图形面积计算器
python
import math
class Shape:
"""图形基类"""
def area(self):
raise NotImplementedError("子类必须实现area方法")
class Rectangle(Shape):
"""矩形"""
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Circle(Shape):
"""圆"""
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
class Triangle(Shape):
"""三角形"""
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
class Parallelogram(Shape):
"""平行四边形"""
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return self.base * self.height
# 测试
shapes = [
Rectangle(5, 3),
Circle(4),
Triangle(6, 4),
Parallelogram(5, 3),
]
for shape in shapes:
print(f"{shape.__class__.__name__} 面积:{shape.area():.2f}")
# 输出:
# Rectangle 面积:15.00
# Circle 面积:50.27
# Triangle 面积:12.00
# Parallelogram 面积:15.00
案例3:电商订单系统
python
class Product:
"""商品类"""
def __init__(self, product_id, name, price):
self.product_id = product_id
self.name = name
self.price = price
def __repr__(self):
return f"{self.name}(¥{self.price})"
class CartItem:
"""购物车项"""
def __init__(self, product, quantity):
self.product = product
self.quantity = quantity
@property
def subtotal(self):
"""小计金额"""
return self.product.price * self.quantity
class ShoppingCart:
"""购物车"""
def __init__(self):
self.items = []
def add_item(self, product, quantity=1):
"""添加商品"""
# 检查是否已存在
for item in self.items:
if item.product.product_id == product.product_id:
item.quantity += quantity
print(f"已更新 {product.name} 数量:{item.quantity}")
return
# 新增
self.items.append(CartItem(product, quantity))
print(f"已添加 {product.name} x {quantity}")
def remove_item(self, product_id):
"""移除商品"""
self.items = [item for item in self.items
if item.product.product_id != product_id]
@property
def total(self):
"""总价"""
return sum(item.subtotal for item in self.items)
def show_cart(self):
"""显示购物车"""
print("\n" + "=" * 40)
print("购物车")
print("=" * 40)
for item in self.items:
print(f"{item.product.name:<15} x {item.quantity:<3} = ¥{item.subtotal:.2f}")
print("-" * 40)
print(f"{'总计':<18} = ¥{self.total:.2f}")
print("=" * 40)
# 测试
cart = ShoppingCart()
p1 = Product("P001", "iPhone", 6999)
p2 = Product("P002", "AirPods", 1299)
p3 = Product("P003", "MacBook", 9999)
cart.add_item(p1) # 已添加 iPhone x 1
cart.add_item(p2, 2) # 已添加 AirPods x 2
cart.add_item(p3) # 已添加 MacBook x 1
cart.show_cart()
cart.remove_item("P002")
cart.show_cart()
常见问题FAQ
Q1:类属性 vs 实例属性
python
class Dog:
kind = "狗" # 类属性,所有对象共享
def __init__(self, name):
self.name = name # 实例属性,每个对象独有
dog1 = Dog("旺财")
dog2 = Dog("小白")
print(dog1.kind) # 狗(类属性)
print(dog2.kind) # 狗(类属性)
print(dog1.name) # 旺财(实例属性)
print(dog2.name) # 小白(实例属性)
Q2:私有属性(封装)
用双下划线开头的是"私有属性",外部不应该直接访问:
python
class Person:
def __init__(self, name, age):
self.__name = name # 私有属性(名字会被混淆)
self.__age = age # 私有属性
def get_info(self):
return f"{self.__name}, {self.__age}"
p = Person("小明", 18)
print(p.get_info()) # 小明, 18
print(p.__name) # 报错!私有属性不能直接访问
Q3:str vs repr
python
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
"""给用户看的字符串"""
return f"Person: {self.name}"
def __repr__(self):
"""给开发者看的字符串"""
return f"Person(name='{self.name}')"
p = Person("小明")
print(str(p)) # Person: 小明
print(repr(p)) # Person(name='小明')
写在最后
这篇文章覆盖了面向对象的核心概念:
- class 定义类
- init 构造函数
- self 当前对象
- 继承:子类复用父类
- 封装:私有属性保护数据
下一篇文章:Python 第一周复习,思维导图 + 10道练习题检测学习成果。
参考资料: