Python类与对象入门
学习目标
通过本集的学习,你将能够:
- 理解面向对象编程的基本概念
- 使用 class 关键字定义类
- 掌握属性和方法的使用
- 创建和使用对象
- 理解 init 构造方法
1. 什么是面向对象?
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,将数据和操作数据的方法封装在一起。
1.1 面向对象 vs 面向过程
# 面向过程:关注"怎么做"
# 计算矩形面积
width = 5
height = 3
area = width * height
print(area)
# 面向对象:关注"是什么"
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(5, 3)
print(rect.area())1.2 类和对象的关系
类(Class) ──→ 蓝图/模板
│
├─→ 属性(Attributes):数据
└─→ 方法(Methods):操作
对象(Object) ──→ 类的实例
│
├─→ 具体的个体
└─→ 拥有类定义的所有属性和方法类和对象的ASCII图:
┌─────────────────┐
│ 类:Car │
├─────────────────┤
│ 属性: │
│ - color │
│ - speed │
├─────────────────┤
│ 方法: │
│ - drive() │
│ - stop() │
└─────────────────┘
│
├─→ 实例化
│
┌─────┴─────┐
▼ ▼
┌─────────┐ ┌─────────┐
│ 对象1 │ │ 对象2 │
│ 红色 │ │ 蓝色 │
│ 100km/h │ │ 80km/h │
└─────────┘ └─────────┘2. 类的定义
2.1 基本类定义
# 最简单的类
class Person:
pass # 空类
# 创建对象
person1 = Person()
person2 = Person()
print(type(person1)) # 输出: <class '__main__.Person'>2.2 带属性的类
class Person:
# 类属性:所有实例共享
species = "人类"
# 实例属性:每个实例独有
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age # 实例属性
# 创建对象
person1 = Person("张三", 25)
person2 = Person("李四", 30)
# 访问属性
print(person1.name) # 输出: 张三
print(person1.age) # 输出: 25
print(person2.name) # 输出: 李四
# 类属性
print(Person.species) # 输出: 人类
print(person1.species) # 输出: 人类
print(person2.species) # 输出: 人类2.3 init 构造方法
class Dog:
def __init__(self, name, breed, age=1):
"""构造方法:创建对象时自动调用"""
self.name = name
self.breed = breed
self.age = age
print(f"一只叫{name}的{breed}出生了!")
# 创建对象
dog1 = Dog("旺财", "金毛", 3)
dog2 = Dog("来福", "柯基") # 使用默认年龄
print(dog1.name) # 输出: 旺财
print(dog2.age) # 输出: 13. 属性与方法
3.1 实例方法
class Circle:
def __init__(self, radius):
self.radius = radius
# 实例方法:第一个参数总是self
def area(self):
"""计算圆的面积"""
import math
return math.pi * self.radius ** 2
def circumference(self):
"""计算圆的周长"""
import math
return 2 * math.pi * self.radius
def resize(self, new_radius):
"""修改半径"""
self.radius = new_radius
# 使用
circle = Circle(5)
print(f"半径: {circle.radius}")
print(f"面积: {circle.area():.2f}")
print(f"周长: {circle.circumference():.2f}")
circle.resize(10)
print(f"\n修改后半径: {circle.radius}")
print(f"修改后面积: {circle.area():.2f}")3.2 类方法和静态方法
class MathUtils:
# 类属性
version = "1.0"
# 实例方法
def instance_method(self):
print("这是实例方法,可以访问self")
# 类方法:用@classmethod装饰器,第一个参数是cls
@classmethod
def class_method(cls):
print("这是类方法,可以访问cls")
print(f"版本: {cls.version}")
# 静态方法:用@staticmethod装饰器,没有特殊参数
@staticmethod
def static_method():
print("这是静态方法,不需要self或cls")
@staticmethod
def add(a, b):
return a + b
# 使用
MathUtils.class_method()
MathUtils.static_method()
print(MathUtils.add(3, 5))
utils = MathUtils()
utils.instance_method()3.3 属性访问控制
class BankAccount:
def __init__(self, balance=0):
self.balance = balance # 公开属性
def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"存款: {amount}")
def withdraw(self, amount):
if 0 < amount <= self.balance:
self.balance -= amount
print(f"取款: {amount}")
else:
print("余额不足")
# 使用
account = BankAccount(1000)
print(f"余额: {account.balance}")
account.deposit(500)
print(f"余额: {account.balance}")
account.withdraw(300)
print(f"余额: {account.balance}")
# 问题:可以直接修改balance
account.balance = 1000000 # 这不太好!
print(f"余额: {account.balance}")
# 使用下划线表示"受保护"的属性
class SafeBankAccount:
def __init__(self, balance=0):
self._balance = balance # 单下划线:建议不要直接访问
def get_balance(self):
return self._balance
def deposit(self, amount):
if amount > 0:
self._balance += amount
def withdraw(self, amount):
if 0 < amount <= self._balance:
self._balance -= amount
safe_account = SafeBankAccount(1000)
print(f"余额: {safe_account.get_balance()}")
# 虽然可以访问 _balance,但不建议
# print(safe_account._balance) # 不推荐!4. 创建对象
4.1 实例化对象
class Student:
def __init__(self, name, student_id, grades=None):
self.name = name
self.student_id = student_id
self.grades = grades or []
def add_grade(self, grade):
self.grades.append(grade)
def get_average(self):
if not self.grades:
return 0
return sum(self.grades) / len(self.grades)
# 创建多个学生对象
student1 = Student("张三", "2024001", [85, 90, 78])
student2 = Student("李四", "2024002", [92, 88, 95])
student3 = Student("王五", "2024003")
student3.add_grade(76)
student3.add_grade(82)
student3.add_grade(80)
# 使用对象
students = [student1, student2, student3]
for student in students:
avg = student.get_average()
print(f"{student.name} ({student.student_id}): 平均分 {avg:.1f}")4.2 对象的内存表示
每个对象在内存中都有独立的存储空间:
student1 ──→ ┌─────────────────┐
│ name: "张三" │
│ student_id: ... │
│ grades: [...] │
└─────────────────┘
student2 ──→ ┌─────────────────┐
│ name: "李四" │
│ student_id: ... │
│ grades: [...] │
└─────────────────┘5. 实用案例
5.1 案例1:简单的购物车
# shopping_cart.py
class Product:
"""商品类"""
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def __str__(self):
return f"{self.name} - ¥{self.price} (库存: {self.stock})"
class ShoppingCart:
"""购物车类"""
def __init__(self):
self.items = {} # {product: quantity}
def add_item(self, product, quantity=1):
"""添加商品到购物车"""
if product.stock < quantity:
print(f"库存不足!{product.name}只剩{product.stock}件")
return
if product in self.items:
self.items[product] += quantity
else:
self.items[product] = quantity
product.stock -= quantity
print(f"已添加 {quantity} 件 {product.name}")
def remove_item(self, product, quantity=None):
"""从购物车移除商品"""
if product not in self.items:
print("购物车中没有此商品")
return
if quantity is None or quantity >= self.items[product]:
product.stock += self.items[product]
del self.items[product]
print(f"已移除 {product.name}")
else:
self.items[product] -= quantity
product.stock += quantity
print(f"已移除 {quantity} 件 {product.name}")
def get_total(self):
"""计算总价"""
total = 0
for product, quantity in self.items.items():
total += product.price * quantity
return total
def show_cart(self):
"""显示购物车内容"""
if not self.items:
print("购物车为空")
return
print("购物车内容:")
for product, quantity in self.items.items():
subtotal = product.price * quantity
print(f" {product.name} x {quantity} = ¥{subtotal}")
print(f"总价: ¥{self.get_total()}")
# 使用
apple = Product("苹果", 5.0, 100)
banana = Product("香蕉", 3.0, 50)
orange = Product("橙子", 4.0, 80)
cart = ShoppingCart()
cart.add_item(apple, 5)
cart.add_item(banana, 3)
cart.add_item(orange, 2)
print()
cart.show_cart()
print()
cart.remove_item(banana, 1)
cart.show_cart()5.2 案例2:学生成绩管理系统
# grade_system.py
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.courses = {} # {course_name: grade}
def add_course(self, course_name, grade):
self.courses[course_name] = grade
def get_gpa(self):
if not self.courses:
return 0
return sum(self.courses.values()) / len(self.courses)
def __str__(self):
return f"{self.name} ({self.student_id})"
class GradeSystem:
def __init__(self):
self.students = {} # {student_id: Student}
def add_student(self, name, student_id):
if student_id in self.students:
print("学号已存在")
return
self.students[student_id] = Student(name, student_id)
print(f"已添加学生: {name}")
def add_grade(self, student_id, course_name, grade):
if student_id not in self.students:
print("学生不存在")
return
self.students[student_id].add_course(course_name, grade)
print(f"已添加成绩: {course_name} - {grade}")
def show_student(self, student_id):
if student_id not in self.students:
print("学生不存在")
return
student = self.students[student_id]
print(f"\n{student}")
print("课程成绩:")
for course, grade in student.courses.items():
print(f" {course}: {grade}")
print(f"GPA: {student.get_gpa():.2f}")
def show_all_students(self):
if not self.students:
print("没有学生")
return
print("\n所有学生:")
for student in self.students.values():
print(f" {student} - GPA: {student.get_gpa():.2f}")
# 使用
system = GradeSystem()
system.add_student("张三", "2024001")
system.add_student("李四", "2024002")
system.add_grade("2024001", "数学", 85)
system.add_grade("2024001", "英语", 90)
system.add_grade("2024001", "物理", 78)
system.add_grade("2024002", "数学", 92)
system.add_grade("2024002", "英语", 88)
system.add_grade("2024002", "物理", 95)
system.show_student("2024001")
system.show_all_students()5.3 案例3:简单的银行账户
# bank_account.py
class BankAccount:
"""银行账户类"""
# 类变量
bank_name = "示例银行"
total_accounts = 0
def __init__(self, owner, initial_balance=0):
self.owner = owner
self._balance = initial_balance # 受保护的余额
self.account_number = self._generate_account_number()
BankAccount.total_accounts += 1
print(f"账户创建成功!{self.owner},账号: {self.account_number}")
def _generate_account_number(self):
"""生成账号(内部方法)"""
return f"ACC{BankAccount.total_accounts + 1:06d}"
def deposit(self, amount):
"""存款"""
if amount <= 0:
print("存款金额必须大于0")
return False
self._balance += amount
print(f"存款成功: ¥{amount},当前余额: ¥{self._balance}")
return True
def withdraw(self, amount):
"""取款"""
if amount <= 0:
print("取款金额必须大于0")
return False
if amount > self._balance:
print(f"余额不足!当前余额: ¥{self._balance}")
return False
self._balance -= amount
print(f"取款成功: ¥{amount},当前余额: �{self._balance}")
return True
def get_balance(self):
"""查询余额"""
return self._balance
def transfer(self, target_account, amount):
"""转账"""
if self.withdraw(amount):
target_account.deposit(amount)
print(f"转账成功: ¥{amount} 从 {self.owner} 到 {target_account.owner}")
return True
return False
def __str__(self):
return f"[{self.account_number}] {self.owner} - 余额: ¥{self._balance}"
# 使用
print(f"欢迎使用 {BankAccount.bank_name}")
print()
account1 = BankAccount("张三", 1000)
account2 = BankAccount("李四", 500)
print()
print(account1)
print(account2)
print(f"总账户数: {BankAccount.total_accounts}")
print()
account1.deposit(500)
account2.withdraw(200)
print()
account1.transfer(account2, 300)
print()
print(account1)
print(account2)6. 自测问题
- 类和对象的关系是什么?
- init 方法的作用是什么?
- 实例方法的第一个参数是什么?
- 类属性和实例属性的区别是什么?
- 什么是封装?
7. 下集预告
下一集我们将学习Python面向对象的进阶内容,包括继承、多态、封装等!
参考资料
- Python官方文档: https://docs.python.org/3/tutorial/classes.html
- 《Python编程:从入门到实践》