Objectives 学习目标
- To appreciate how defining new classes can provide structure for a complex program 理解定义新类如何为复杂程序提供结构
- To be able to read and write Python class definitions 能够阅读和编写Python类定义
- To understand the concept of encapsulation and how it contributes to building modular and maintainable programs 理解封装概念及其如何帮助构建模块化和可维护的程序
- To be able to write programs involving simple class definitions 能够编写涉及简单类定义的程序
- To be able to write interactive graphics programs involving novel (programmer designed) widgets 能够编写涉及新颖(程序员设计)小部件的交互式图形程序
Quick Review of Objects 对象快速回顾
Object Concept 对象概念
# 对象:知道事情并能做事情的活跃数据类型
class Circle:
def __init__(self, center, radius):
self.center = center # 实例变量 - 知道的事情
self.radius = radius # 实例变量 - 知道的事情
def draw(self): # 方法 - 能做的事情
print(f"Drawing circle at {self.center} with radius {self.radius}")
def move(self, dx, dy): # 方法 - 能做的事情
self.center = (self.center[0] + dx, self.center[1] + dy)
print(f"Moved circle to {self.center}")
# 创建对象实例
myCircle = Circle((0, 0), 20) # 构造函数
myCircle.draw() # 调用方法
myCircle.move(10, 10.5) # 调用方法Object Attributes 对象属性
class Student:
def __init__(self, name, hours, qpoints):
self.name = name # 实例变量
self.hours = float(hours) # 实例变量
self.qpoints = float(qpoints) # 实例变量
def getName(self): # 方法
return self.name
def getHours(self): # 方法
return self.hours
def getQPoints(self): # 方法
return self.qpoints
def gpa(self): # 方法
return self.qpoints / self.hours if self.hours > 0 else 0.0
# 使用对象
student1 = Student("John Doe", 127, 228)
print(f"Name: {student1.getName()}")
print(f"GPA: {student1.gpa():.2f}")Code Reuse and Modular Design 代码重用与模块化设计
Levels of Abstraction 抽象层次
# 层次1:函数 - 代码级抽象
def calculate_area(radius):
"""计算圆面积"""
return 3.14159 * radius ** 2
# 层次2:对象 - 数据和功能的进一步抽象
class Circle:
def __init__(self, radius):
self.radius = radius
self.area = self.calculate_area()
def calculate_area(self):
return 3.14159 * self.radius ** 2
def get_area(self):
return self.area
# 使用比较
radius = 5
area_function = calculate_area(radius) # 函数方式
circle_object = Circle(radius) # 对象方式
area_object = circle_object.get_area()
print(f"函数计算面积: {area_function}")
print(f"对象计算面积: {area_object}")Cannonball Program Specification 炮弹程序规范
Problem Analysis 问题分析
# 输入参数
# - 发射角度(度)
# - 初始速度(米/秒)
# - 初始高度(米)
# 输出:炮弹在击中地面前行进的距离(米)
def cannonball_simulation():
"""
炮弹飞行模拟 - 面向过程设计
"""
# 获取输入
angle = float(input("发射角度(度): "))
velocity = float(input("初始速度(米/秒): "))
height = float(input("初始高度(米): "))
# 计算初始位置和速度分量
xpos = 0.0
ypos = height
# 角度转弧度
import math
theta = math.radians(angle)
xvel = velocity * math.cos(theta)
yvel = velocity * math.sin(theta)
# 时间间隔
time_interval = 0.1
# 模拟循环
while ypos >= 0.0:
# 更新位置和速度
xpos = xpos + time_interval * xvel
yvel1 = yvel - time_interval * 9.8 # 重力加速度
ypos = ypos + time_interval * (yvel + yvel1) / 2.0
yvel = yvel1
print(f"位置: ({xpos:.2f}, {ypos:.2f})")
print(f"\n炮弹飞行距离: {xpos:.2f} 米")
return xpos
# 运行模拟
# cannonball_simulation()Modular Process-Oriented Design 模块化面向过程设计
import math
def get_inputs():
"""获取用户输入"""
angle = float(input("发射角度(度): "))
velocity = float(input("初始速度(米/秒): "))
height = float(input("初始高度(米): "))
time_interval = 0.1
return angle, velocity, height, time_interval
def get_xy_components(velocity, angle):
"""计算速度的x和y分量"""
theta = math.radians(angle)
xvel = velocity * math.cos(theta)
yvel = velocity * math.sin(theta)
return xvel, yvel
def update_cannonball(time, xpos, ypos, xvel, yvel):
"""更新炮弹位置和速度"""
yvel1 = yvel - time * 9.8
ypos = ypos + time * (yvel + yvel1) / 2.0
xpos = xpos + time * xvel
return xpos, ypos, yvel1
def main_process():
"""主程序 - 面向过程"""
angle, velocity, height, time = get_inputs()
xpos, ypos = 0.0, height
xvel, yvel = get_xy_components(velocity, angle)
while ypos >= 0:
xpos, ypos, yvel = update_cannonball(time, xpos, ypos, xvel, yvel)
print(f"\n飞行距离: {xpos:.1f} 米")
# 问题:参数太多,代码不够清晰Object-Oriented Design 面向对象设计
Projectile Class 炮弹类
import math
class Projectile:
"""
炮弹类 - 面向对象设计
封装炮弹的物理属性和行为
"""
def __init__(self, angle, velocity, height):
"""构造函数 - 初始化炮弹"""
# 位置分量
self.xpos = 0.0
self.ypos = height
# 速度分量
theta = math.radians(angle)
self.xvel = velocity * math.cos(theta)
self.yvel = velocity * math.sin(theta)
# 物理常量
self.gravity = 9.8
def update(self, time):
"""更新炮弹位置 - 经过time秒后"""
# 更新x位置(忽略空气阻力)
self.xpos = self.xpos + time * self.xvel
# 计算新的y速度
yvel1 = self.yvel - time * self.gravity
# 更新y位置(使用平均速度)
self.ypos = self.ypos + time * (self.yvel + yvel1) / 2.0
# 更新y速度
self.yvel = yvel1
def get_x(self):
"""获取x坐标"""
return self.xpos
def get_y(self):
"""获取y坐标"""
return self.ypos
def is_above_ground(self):
"""检查炮弹是否还在空中"""
return self.ypos >= 0
def main_oo():
"""主程序 - 面向对象版本"""
# 获取输入
angle = float(input("发射角度(度): "))
velocity = float(input("初始速度(米/秒): "))
height = float(input("初始高度(米): "))
# 创建炮弹对象
cannonball = Projectile(angle, velocity, height)
time_interval = 0.1
# 模拟循环
while cannonball.is_above_ground():
cannonball.update(time_interval)
print(f"位置: ({cannonball.get_x():.2f}, {cannonball.get_y():.2f})")
print(f"\n炮弹飞行距离: {cannonball.get_x():.2f} 米")
# 优势:代码更清晰,逻辑更明确Example: Multi-Sided Dice 示例:多面骰子
MSDie Class Implementation MSDie类实现
import random
class MSDie:
"""
多面骰子类
"""
def __init__(self, sides):
"""构造函数 - 初始化骰子"""
self.sides = sides # 骰子面数
self.value = 1 # 当前值
self.roll_history = [] # 投掷历史
def roll(self):
"""投掷骰子 - 随机设置值"""
self.value = random.randint(1, self.sides)
self.roll_history.append(self.value)
return self.value
def set_value(self, value):
"""设置骰子值(作弊功能)"""
if 1 <= value <= self.sides:
self.value = value
self.roll_history.append(f"set:{value}")
else:
print(f"错误:值必须在1到{self.sides}之间")
def get_value(self):
"""获取当前值"""
return self.value
def get_sides(self):
"""获取面数"""
return self.sides
def get_history(self):
"""获取投掷历史"""
return self.roll_history
def __str__(self):
"""字符串表示"""
return f"MSDie({self.sides}): {self.value}"
def __repr__(self):
"""详细字符串表示"""
return f"MSDie(sides={self.sides}, value={self.value}, history={self.roll_history})"
# 测试骰子类
def test_dice():
print("=== 多面骰子测试 ===")
# 创建6面骰子
die1 = MSDie(6)
print(f"初始值: {die1.get_value()}")
# 投掷几次
for i in range(3):
die1.roll()
print(f"第{i+1}次投掷: {die1.get_value()}")
# 设置特定值
die1.set_value(4)
print(f"设置后的值: {die1.get_value()}")
# 查看历史
print(f"投掷历史: {die1.get_history()}")
# 创建13面骰子
die2 = MSDie(13)
die2.roll()
print(f"\n13面骰子: {die2.get_value()}")
# 测试字符串表示
print(f"骰子1: {die1}")
print(f"骰子2: {repr(die2)}")
# test_dice()Data Processing with Class 使用类进行数据处理
Student Record Class 学生记录类
class Student:
"""
学生类 - 用于数据处理
"""
def __init__(self, name, hours, qpoints):
"""构造函数"""
self.name = name
self.hours = float(hours)
self.qpoints = float(qpoints)
def getName(self):
"""获取姓名"""
return self.name
def getHours(self):
"""获取学时"""
return self.hours
def getQPoints(self):
"""获取绩点"""
return self.qpoints
def gpa(self):
"""计算GPA"""
return self.qpoints / self.hours if self.hours > 0 else 0.0
def __str__(self):
"""字符串表示"""
return f"{self.name}: {self.hours}学时, GPA={self.gpa():.2f}"
def find_best_student(filename):
"""
从数据文件中找到GPA最高的学生
"""
try:
with open(filename, 'r') as file:
best_student = None
for line in file:
# 解析每行数据
data = line.strip().split()
if len(data) >= 3:
# 组合姓名(可能包含空格)
name = ' '.join(data[:-2])
hours = data[-2]
qpoints = data[-1]
# 创建学生对象
student = Student(name, hours, qpoints)
# 更新最佳学生
if best_student is None or student.gpa() > best_student.gpa():
best_student = student
return best_student
except FileNotFoundError:
print(f"错误:文件 {filename} 未找到")
return None
def create_sample_data():
"""创建示例数据文件"""
sample_data = """Adams, Henry 127 228
Comptewell, Susan 100 400
DibbleBit, Denny 18 41.5
Jones, Jim 48.5 155
Smith, Frank 37 125.33"""
with open('students.txt', 'w') as f:
f.write(sample_data)
def process_student_data():
"""处理学生数据"""
# 创建示例数据
create_sample_data()
# 查找最佳学生
best = find_best_student('students.txt')
if best:
print("=== 最佳学生 ===")
print(f"姓名: {best.getName()}")
print(f"学时: {best.getHours()}")
print(f"绩点: {best.getQPoints()}")
print(f"GPA: {best.gpa():.3f}")
else:
print("未找到学生数据")
# process_student_data()Modules and Namespaces 模块与命名空间
Module Creation and Usage 模块创建与使用
# projectile.py 模块文件
"""
projectile.py
炮弹物理模拟模块
提供Projectile类用于模拟抛射物运动
"""
import math
class Projectile:
"""抛射物类 - 模拟物体在重力下的运动"""
def __init__(self, angle, velocity, height):
self.xpos = 0.0
self.ypos = height
theta = math.radians(angle)
self.xvel = velocity * math.cos(theta)
self.yvel = velocity * math.sin(theta)
self.gravity = 9.8
def update(self, time):
self.xpos += time * self.xvel
yvel1 = self.yvel - time * self.gravity
self.ypos += time * (self.yvel + yvel1) / 2.0
self.yvel = yvel1
def getX(self): return self.xpos
def getY(self): return self.ypos
# 模块测试代码
if __name__ == "__main__":
# 测试代码
p = Projectile(45, 50, 0)
print("模块测试通过")
# main_program.py 主程序文件
"""
主程序 - 使用projectile模块
"""
# 方法1:导入整个模块
import projectile
def main():
ball = projectile.Projectile(45, 50, 10)
print(f"初始位置: ({ball.getX()}, {ball.getY()})")
# 方法2:导入特定类
from projectile import Projectile
def main2():
ball = Projectile(45, 50, 10)
print(f"初始位置: ({ball.getX()}, {ball.getY()})")
# 方法3:导入所有(不推荐)
# from projectile import *
# 查看模块文档
# help(projectile)Package Structure 包结构
"""
包示例结构:
physics/
__init__.py # 包初始化文件
projectile.py # 抛射物模块
vectors.py # 向量模块
constants.py # 物理常量模块
graphics/
__init__.py
widgets.py
animations.py
main.py # 主程序
"""
# physics/__init__.py
"""
physics 包
物理模拟相关模块
"""
from .projectile import Projectile
from .vectors import Vector2D
__all__ = ['Projectile', 'Vector2D']
# 使用包
# from physics import Projectile, Vector2D
# 或
# import physics.projectileEncapsulation and Abstraction 封装与抽象
Encapsulation Benefits 封装优势
class BankAccount:
"""
银行账户类 - 展示封装优势
"""
def __init__(self, account_holder, initial_balance=0):
self.account_holder = account_holder
self._balance = initial_balance # 受保护变量
self._transaction_history = [] # 内部实现细节
def deposit(self, amount):
"""存款 - 公开接口"""
if amount > 0:
self._balance += amount
self._transaction_history.append(f"存款: +${amount}")
return True
return False
def withdraw(self, amount):
"""取款 - 公开接口"""
if 0 < amount <= self._balance:
self._balance -= amount
self._transaction_history.append(f"取款: -${amount}")
return True
return False
def get_balance(self):
"""获取余额 - 公开接口"""
return self._balance
def get_statement(self):
"""获取对账单 - 不暴露内部数据结构"""
statement = f"账户持有人: {self.account_holder}\n"
statement += f"当前余额: ${self._balance:.2f}\n"
statement += "最近交易:\n"
for transaction in self._transaction_history[-5:]: # 只显示最近5笔
statement += f" {transaction}\n"
return statement
# 不提供直接访问_transaction_history的方法
# 保护内部实现细节
# 使用封装类
account = BankAccount("张三", 1000)
account.deposit(500)
account.withdraw(200)
print(account.get_statement())
# 优势:
# 1. 内部实现可以改变而不影响使用者
# 2. 数据验证和业务逻辑集中管理
# 3. 使用更简单,不需要了解内部细节Widgets and GUI Programming 小部件与GUI编程
Button Class 按钮类
from graphics import *
class Button:
"""
按钮类 - 自定义GUI小部件
"""
def __init__(self, win, center, width, height, label):
"""初始化按钮"""
self.win = win
self.center = center
self.width = width
self.height = height
self.label = label
self.active = False
# 创建按钮视觉元素
x, y = center.getX(), center.getY()
w, h = width/2, height/2
# 按钮矩形
self.rect = Rectangle(Point(x-w, y-h), Point(x+w, y+h))
self.rect.setFill('lightgray')
self.rect.draw(win)
# 按钮标签
self.text = Text(center, label)
self.text.draw(win)
# 初始状态
self.deactivate()
def activate(self):
"""激活按钮"""
self.active = True
self.rect.setFill('lightgreen')
self.text.setStyle('bold')
def deactivate(self):
"""停用按钮"""
self.active = False
self.rect.setFill('lightgray')
self.text.setStyle('normal')
def clicked(self, p):
"""检查点击"""
if not self.active:
return False
x, y = self.center.getX(), self.center.getY()
w, h = self.width/2, self.height/2
# 检查点是否在按钮区域内
return (x-w <= p.getX() <= x+w and
y-h <= p.getY() <= y+h)
def getLabel(self):
"""获取标签"""
return self.label
def setLabel(self, new_label):
"""设置新标签"""
self.label = new_label
self.text.setText(new_label)DieView Class 骰子视图类
from graphics import *
class DieView:
"""
骰子视图类 - 显示骰子面
"""
def __init__(self, win, center, size):
"""初始化骰子视图"""
self.win = win
self.center = center
self.size = size
self.value = 1
# 创建骰子正方形
half = size/2
x, y = center.getX(), center.getY()
self.background = Rectangle(Point(x-half, y-half),
Point(x+half, y+half))
self.background.setFill('white')
self.background.setOutline('black')
self.background.draw(win)
# 创建所有可能的点(pip)
self.pips = []
self.__create_pips()
# 设置初始值
self.setValue(1)
def __create_pips(self):
"""创建骰子上的点"""
# 点的相对位置(百分比坐标)
positions = [
[(0.5, 0.5)], # 1
[(0.25, 0.25), (0.75, 0.75)], # 2
[(0.25, 0.25), (0.5, 0.5), (0.75, 0.75)], # 3
[(0.25, 0.25), (0.25, 0.75),
(0.75, 0.25), (0.75, 0.75)], # 4
[(0.25, 0.25), (0.25, 0.75), (0.5, 0.5),
(0.75, 0.25), (0.75, 0.75)], # 5
[(0.25, 0.25), (0.25, 0.5), (0.25, 0.75),
(0.75, 0.25), (0.75, 0.5), (0.75, 0.75)] # 6
]
# 创建点对象
for pip_positions in positions:
pip_group = []
for pos in pip_positions:
x = self.center.getX() + (pos[0] - 0.5) * self.size * 0.6
y = self.center.getY() + (pos[1] - 0.5) * self.size * 0.6
pip = Circle(Point(x, y), self.size * 0.1)
pip.setFill('black')
pip_group.append(pip)
self.pips.append(pip_group)
def setValue(self, value):
"""设置骰子值"""
if 1 <= value <= 6:
self.value = value
self.__update_display()
def __update_display(self):
"""更新显示"""
# 隐藏所有点
for pip_group in self.pips:
for pip in pip_group:
pip.undraw()
# 显示当前值的点
for pip in self.pips[self.value - 1]:
pip.draw(self.win)
def getValue(self):
"""获取当前值"""
return self.valueDice Roller Application 骰子滚动器应用
Complete Dice Roller 完整骰子滚动器
from graphics import *
from random import randint
def dice_roller():
"""骰子滚动器主程序"""
# 创建窗口
win = GraphWin("骰子滚动器", 400, 300)
win.setBackground("white")
# 创建骰子
die1 = DieView(win, Point(150, 150), 60)
die2 = DieView(win, Point(250, 150), 60)
# 创建按钮
roll_button = Button(win, Point(150, 250), 80, 30, "滚动")
quit_button = Button(win, Point(250, 250), 80, 30, "退出")
# 激活滚动按钮,停用退出按钮
roll_button.activate()
quit_button.deactivate()
# 第一次滚动
die1.setValue(randint(1, 6))
die2.setValue(randint(1, 6))
quit_button.activate() # 至少滚动一次后才能退出
# 事件循环
while True:
click = win.getMouse()
if roll_button.clicked(click):
# 滚动骰子
die1.setValue(randint(1, 6))
die2.setValue(randint(1, 6))
quit_button.activate()
elif quit_button.clicked(click):
break
# 清理
win.close()
# 注意:需要先实现Button和DieView类
# dice_roller()Animated Cannonball 动画炮弹
ShotTracker Class 炮弹轨迹类
from graphics import *
from projectile import Projectile
class ShotTracker:
"""
炮弹轨迹跟踪器 - 结合物理模拟和图形显示
"""
def __init__(self, win, angle, velocity, height):
"""初始化炮弹跟踪器"""
self.win = win
# 物理模拟部分
self.proj = Projectile(angle, velocity, height)
# 图形显示部分
self.marker = Circle(Point(0, 0), 3)
self.marker.setFill("red")
self.marker.setOutline("red")
self.marker.draw(win)
# 更新初始位置
self.update(0)
def update(self, dt):
"""更新炮弹位置"""
# 更新物理模拟
self.proj.update(dt)
# 更新图形位置
x = self.proj.getX()
y = self.win.getHeight() - self.proj.getY() # 转换坐标系
# 移动标记
center = self.marker.getCenter()
dx = x - center.getX()
dy = y - center.getY()
self.marker.move(dx, dy)
def getX(self):
"""获取x坐标"""
return self.proj.getX()
def getY(self):
"""获取y坐标"""
return self.proj.getY()
def is_above_ground(self):
"""检查是否在地面以上"""
return self.proj.getY() >= 0
def undraw(self):
"""移除图形"""
self.marker.undraw()InputDialog Class 输入对话框类
class InputDialog:
"""
输入对话框类 - 获取用户输入
"""
def __init__(self, angle, vel, height):
"""初始化对话框"""
self.win = GraphWin("发射参数", 300, 200)
self.win.setBackground("lightblue")
# 创建输入框和标签
Text(Point(50, 30), "角度:").draw(self.win)
self.angle_entry = Entry(Point(150, 30), 10)
self.angle_entry.setText(str(angle))
self.angle_entry.draw(self.win)
Text(Point(50, 60), "速度:").draw(self.win)
self.vel_entry = Entry(Point(150, 60), 10)
self.vel_entry.setText(str(vel))
self.vel_entry.draw(self.win)
Text(Point(50, 90), "高度:").draw(self.win)
self.height_entry = Entry(Point(150, 90), 10)
self.height_entry.setText(str(height))
self.height_entry.draw(self.win)
# 创建按钮
self.fire_button = Button(self.win, Point(100, 140), 60, 25, "发射")
self.quit_button = Button(self.win, Point(200, 140), 60, 25, "退出")
self.fire_button.activate()
self.quit_button.activate()
def interact(self):
"""与用户交互"""
while True:
click = self.win.getMouse()
if self.quit_button.clicked(click):
self.win.close()
return None, None, None, "Quit"
if self.fire_button.clicked(click):
try:
angle = float(self.angle_entry.getText())
vel = float(self.vel_entry.getText())
height = float(self.height_entry.getText())
self.win.close()
return angle, vel, height, "Fire"
except ValueError:
# 输入无效,继续等待
pass
def close(self):
"""关闭对话框"""
self.win.close()Complete Animation 完整动画程序
def animated_cannonball():
"""动画炮弹主程序"""
# 创建主窗口
win = GraphWin("炮弹模拟", 640, 480, autoflush=False)
win.setCoords(-10, -10, 210, 155)
win.setBackground("lightblue")
# 绘制地面
ground = Line(Point(-10, 0), Point(210, 0))
ground.setWidth(3)
ground.draw(win)
# 初始参数
angle, vel, height = 45.0, 40.0, 2.0
while True:
# 获取输入
input_dialog = InputDialog(angle, vel, height)
result = input_dialog.interact()
if result[3] == "Quit":
break
angle, vel, height, _ = result
# 创建炮弹
shot = ShotTracker(win, angle, vel, height)
# 动画循环
dt = 1.0 / 30 # 30帧每秒
while shot.is_above_ground() and shot.getX() < 210:
shot.update(dt)
update(30) # 限制帧率
# 等待点击继续
if shot.is_above_ground():
Text(Point(100, 140), "炮弹飞出边界!").draw(win)
else:
Text(Point(100, 140), f"距离: {shot.getX():.1f}").draw(win)
win.getMouse()
# 清理文本
for item in win.items[:]:
if isinstance(item, Text):
item.undraw()
shot.undraw()
win.close()
# 注意:需要完整的图形库支持
# animated_cannonball()Class Attributes and Methods 类属性与方法
Class Attributes 类属性
class Student:
"""
学生类 - 演示类属性
"""
# 类属性 - 所有实例共享
school_name = "Python University"
total_students = 0
gpa_scale = 4.0
def __init__(self, name, hours, qpoints):
"""实例构造函数"""
self.name = name
self.hours = float(hours)
self.qpoints = float(qpoints)
# 更新类属性
Student.total_students += 1
self.student_id = Student.total_students
def gpa(self):
"""实例方法"""
return self.qpoints / self.hours if self.hours > 0 else 0.0
@classmethod
def get_school_info(cls):
"""类方法 - 操作类属性"""
return f"{cls.school_name} - 总学生数: {cls.total_students}"
@classmethod
def set_gpa_scale(cls, new_scale):
"""类方法 - 修改类属性"""
cls.gpa_scale = new_scale
return f"GPA标准已更新为: {cls.gpa_scale}"
@classmethod
def create_from_string(cls, student_string):
"""类方法 - 替代构造函数"""
# 格式: "姓名,学时,质量点"
name, hours, qpoints = student_string.split(',')
return cls(name.strip(), hours.strip(), qpoints.strip())
@staticmethod
def calculate_gpa(hours, qpoints):
"""静态方法 - 不依赖于实例或类"""
return qpoints / hours if hours > 0 else 0.0
# 使用类属性和方法
def test_class_attributes():
print("=== 类属性与方法测试 ===")
# 访问类属性
print(f"学校: {Student.school_name}")
print(f"总学生: {Student.total_students}")
# 创建实例
student1 = Student("Alice", 120, 360)
student2 = Student("Bob", 90, 315)
print(f"总学生: {Student.total_students}")
print(f"学生1 ID: {student1.student_id}")
print(f"学生2 ID: {student2.student_id}")
# 调用类方法
print(Student.get_school_info())
print(Student.set_gpa_scale(5.0))
# 使用替代构造函数
student3 = Student.create_from_string("Charlie, 100, 380")
print(f"学生3: {student3.name}, GPA: {student3.gpa():.2f}")
# 调用静态方法
gpa = Student.calculate_gpa(100, 380)
print(f"静态方法计算GPA: {gpa:.2f}")
# test_class_attributes()Summary 总结
Key Concepts 关键概念
-
Object-Oriented Programming面向对象编程
- Classes as blueprints for objects 类作为对象的蓝图
- Objects encapsulate data and behavior 对象封装数据和行为
- Inheritance, polymorphism, encapsulation 继承、多态、封装
-
Class Definition类定义
__init__constructor method__init__构造方法- Instance variables and methods 实例变量和方法
- Self parameter reference self参数引用
-
Encapsulation封装
- Hide implementation details 隐藏实现细节
- Provide clean interfaces 提供清晰接口
- Improve maintainability 提高可维护性
-
Class vs Instance类与实例
- Class attributes shared by all instances 类属性被所有实例共享
- Instance attributes unique to each object 实例属性每个对象独有
- Class methods and static methods 类方法和静态方法
-
GUI ProgrammingGUI编程
- Custom widget creation 自定义小部件创建
- Event-driven programming 事件驱动编程
- Animation techniques 动画技术
Design Principles 设计原则
- Process-Oriented Design面向过程设计: Focus on steps and procedures 关注步骤和过程
- Object-Oriented Design面向对象设计: Focus on objects and their interactions 关注对象及其交互
- Choose appropriate approach based on problem complexity 根据问题复杂度选择合适方法
- Use encapsulation to create modular code 使用封装创建模块化代码
通过定义类,可以创建更结构化、可维护和可重用的代码,构建复杂的软件系统!