学习目标:Python - 100天一起从新手到大师
学习时间:
提示:个人自定义
例:
- 周一至周五晚上 9:00 点—中午12:00点整(早上学习Python,下午上班挣窝囊废给公司开发鸿蒙APP)
- 周六上午 10点-上午 11 点
- 周日下午 3 点-下午 6 点
Python 学习笔记(第1天)---初识python
一、Python 简介:为什么要学它?
- 诞生:1989年,荷兰程序员吉多·范罗苏姆(Guido van Rossum)为打发圣诞节假期,开发了Python(名字灵感来自他最爱的英剧《蒙提·派森的飞行马戏团》)。
- 发展:1991年发布第一个公开版本(Python 0.9.0),2000年Python 2发布(长期维护至2020年),2008年Python 3发布(现主流版本)。
- 现状:全球开发者社区庞大,TIOBE榜单常年位列前三(2023年排名第一),被称为“胶水语言”(能连接其他语言)。
2. 优缺点:新手友好的“全能选手”
| 优点 | 缺点 | 记忆口诀 |
|---|---|---|
| 语法简单(像说英语) | 运行速度比C/Java慢 | 简单≠快,适合快速开发 |
| 库多(不用重复造轮子) | 多线程受GIL限制(CPU密集型任务弱) | 库多省时间,性能看场景 |
| 跨平台(Windows/macOS/Linux通用) | 动态类型(大型项目易出错) | 跨平台爽,类型要自己管 |
3. 应用领域:生活处处有python
- 数据分析:用Pandas处理Excel表格,用Matplotlib画图表(比如统计每月零花钱)。
- AI/机器学习:用TensorFlow/PyTorch训练模型(比如识别猫和狗的照片)。
- Web开发:用Django/Flask做网站(比如班级博客、小商城)。
- 自动化:用脚本批量重命名文件、自动发邮件(比如每天自动备份手机照片)。
二、搭建编程环境:电脑准备“Python小窝”
目标:让电脑能“听懂”Python代码。
步骤:
- 下载安装包:去Python官网 → 点击“Downloads” → 选最新版Python 3(如3.12)→ 下载Windows安装包(
.exe文件)。 - 安装时勾选关键选项:
- 勾选“Add Python to PATH”(自动配置环境变量,否则需手动设置)。
- 选“Install Now”(默认安装)。
- 验证安装:
打开“命令提示符”(Win+R输入cmd回车)→ 输入python --version→ 显示版本号(如Python 3.12.0)即成功!
2. macOS系统(苹果电脑)
步骤:
- 检查是否预装:打开“终端”(应用程序→实用工具→终端)→ 输入
python3 --version→ 若显示版本号(如Python 3.9.7),无需安装。 - 未预装则手动装:
- 用Homebrew(推荐):终端输入
brew install python3。 - 官网下载:同Windows步骤,选macOS安装包。
- 用Homebrew(推荐):终端输入
- 验证:终端输入
python3 --version→ 显示版本即成功!
3. Linux系统(如Ubuntu)
步骤:
- 检查是否预装:终端输入
python3 --version→ 多数Linux已预装Python 3。 - 未预装则安装:终端输入
sudo apt update && sudo apt install python3(需管理员权限)。 - 验证:同上,输入
python3 --version→ 显示版本即成功!
新手提示:安装后建议同时安装VS Code(代码编辑器)或PyCharm(专业IDE),但本阶段用系统自带终端也能跑通!
三、从终端运行Python程序:让电脑“开口说话”
目标:写一行代码,让电脑输出“Hello, world!”(编程入门仪式感拉满)。
1. 第一行Python代码:print函数
Python用 print() 函数输出内容(括号内放要打印的文字,文字用引号包裹)。
示例代码:
print("Hello, world!") # 输出:Hello, world!
print("你好,Python!") # 输出:你好,Python!
print(1 + 2) # 输出:3(数字也能直接打印)
2. 终端运行步骤
以Windows为例(macOS/Linux类似):
- 新建文件:用记事本(或VS Code)新建文件,命名为
hello.py(注意扩展名是.py)。 - 写入代码:在文件中输入
print("Hello, world!")→ 保存。 - 运行程序:
- 打开命令提示符(CMD)→ 输入
cd 文件路径(如cd C:\Users\你的名字,切换到文件所在文件夹)。 - 输入
python hello.py→ 回车 → 看到Hello, world!”即成功!
- 打开命令提示符(CMD)→ 输入
常见问题:
- 报错
NameError: name 'python' is not recognized→ 说明环境变量没配好(安装时没勾选“Add to PATH”,需手动配置)。 - 报错
FileNotFoundError→ 检查文件名是否正确(是否是hello.py,路径是否正确)。
四、使用IDLE:Python自带的“练习本”
IDLE(Integrated DeveLopment Environment)是Python自带的简易开发工具,适合新手写小代码。
1. 打开IDLE
- Windows:开始菜单搜索“IDLE” → 点击打开(界面像小黑框+文本框)。
- macOS/Linux:终端输入
idle3→ 回车打开。
2. 交互式环境(REPL):边输边看
IDLE默认进入交互式模式(REPL:Read-Eval-Print Loop),输入代码后立即执行并显示结果。
示例:
>>> print("Hello") # 输入后按回车
Hello # 立即输出结果
>>> 10 + 20
30
>>> x = 5 # 定义变量
>>> x * 3
15
3. 编写多行代码:用“代码编辑器”
IDLE支持写多行代码(如函数、循环),保存后运行。
步骤:
- 在IDLE中点击顶部菜单
File → New File(新建空白编辑窗口)。 - 输入多行代码(如打印1-5的数):
-
for i in range(1, 6): print(i) # 缩进!Python用缩进表示代码块 - 保存文件:
File → Save→ 命名为loop.py(保存到容易找的位置)。 - 运行程序:
Run → Run Module(或按F5)→ 回到交互式窗口,输入loop.py的路径 → 看到输出1 2 3 4 5。
退出IDLE
- 交互式模式:输入
exit()或quit()→ 回车退出。 - 编辑模式:关闭窗口即可(或点击顶部
File → Exit)。
五、注释:给代码“写说明书”
注释是代码中“不执行”的说明文字,用于解释代码功能(自己或他人看懂)。
1. 注释的作用
- 新手友好:帮自己回忆代码逻辑(比如“这里是计算总价”)。
- 团队协作:让其他开发者快速理解你的代码。
2. 单行注释:用#
以 # 开头,后面的内容会被Python忽略(仅注释当前行)。
示例:
# 这是单行注释:计算两个数的和
a = 10 # 变量a存储第一个数
b = 20 # 变量b存储第二个数
sum_ab = a + b # 计算和
print(sum_ab) # 输出结果:30
3. 多行注释:用'''或"""
用三个单引号 ''' 或三个双引号 """ 包裹多行文字(可跨越多行)。
示例:
'''
这是一个多行注释:
功能:计算圆的面积
公式:面积 = π × 半径²
作者:小明
日期:2025-07-15
'''
import math # 导入数学库(π在math.pi里)
radius = 5 # 半径
area = math.pi * radius ** 2 # 计算面积
print(f"半径{radius}的圆面积是:{area}") # 输出结果
新手提示:注释不是越多越好!关键代码(如复杂逻辑、易错步骤)加注释即可,简单的代码(如 a = 10)可以不加。
Day-01总结:新手必记清单
- Python历史:吉多开发,2008年Python 3是主流。
- 优点:简单、库多、跨平台;缺点:慢、多线程弱。
- 环境搭建:Windows/macOS/Linux都能装,终端输入
python --version验证。 - 运行程序:用
print()输出,终端输入python 文件名.py。 - IDLE:交互式模式边输边看,编辑模式写多行代码。
- 注释:
#单行,'''或"""多行,解释代码逻辑。
Python 学习笔记(第2天)--语言元素
一、程序和进制:计算机的“语言密码”
-
程序与指令
- 程序:就是“按顺序执行的一系列指令”,就像做菜的菜谱(先放油→再放菜→最后加盐)。
- 指令:计算机能听懂的“小任务”(比如“计算1+1”“显示‘你好’”)。
-
冯诺依曼机:计算机的“身体结构”
- 计算机的核心工作方式:存储程序 + 程序控制(就像你按菜谱做菜,菜谱(程序)存在大脑(内存)里,一步步执行)。
-
进制:计算机的“语言”
-
计算机只认识 二进制(0和1),但人类用其他进制更方便:
| 进制 | 基数 | 表示符号 | 例子 | 用途 |
|---|---|---|---|---|
| 十进制 | 10 | 0-9 | 10、25、100 | 日常计数 |
| 二进制 | 2 | 0-1 | 1010、111 | 计算机底层存储 |
| 八进制 | 8 | 0-7 | 12、77 | 早期系统权限表示(少用) |
| 十六进制 | 16 | 0-9/A-F | 0xA、0xFF | 颜色代码、内存地址(常用) |
小练习:
- 十进制转二进制:25 → 11001(25÷2=12余1→12÷2=6余0→…倒序写余数)
- 十六进制转十进制:0xB → 11(B=11)
二、变量和类型:给数据“贴标签”
1.变量:数据的“容器”
- 作用:存储数据,方便后续使用(像盒子装苹果,变量名是“苹果盒”)。
- 命名规则:
✅ 只能是字母、数字、下划线(不能以数字开头);
✅ 不能是Python关键字(如if、for);
✅ 区分大小写(age和Age是不同变量)。 - 示例:
name = "小明" # 字符串变量(存文本)
age = 18 # 整数变量(存数字)
score = 90.5 # 浮点数变量(存小数)
is_student = True # 布尔变量(存True/False)
2.input函数:让用户“输入数据”
- 作用:在屏幕上显示提示语,等待用户输入内容(输入的内容默认是字符串类型)。
- 示例:
name = input("请输入你的名字:") # 用户输入“小红”,name变量存"小红"(字符串)
age = input("请输入你的年龄:") # 用户输入“20”,age变量存"20"(字符串)
print(f"你好,{name}!你{age}岁了~") # 输出:你好,小红!你20岁了~
3.检查变量类型 & 类型转换
- 检查类型:用
type(变量名),返回变量的类型(如str、int)。 - 类型转换:用
int()、str()、float()强制转换类型(注意:字符串转数字时,内容必须是纯数字)。 - 示例:
age_str = input("请输入年龄:") # 用户输入"20",age_str是字符串"20"
age_int = int(age_str) # 转成整数20
print(type(age_str)) # 输出:<class 'str'>(原类型是字符串)
print(type(age_int)) # 输出:<class 'int'>(转成整数后)
height = 1.75
height_str = str(height) # 转成字符串"1.75"
print(f"你的身高是{height_str}米") # 输出:你的身高是1.75米
三、数字和字符串:数据的“具体形式”
1.数字类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 整数 | 没有小数点的数 | 10、-5、0 |
| 浮点数 | 有小数点的数(或科学计数法) | 3.14、-2.5、1e3(=1000) |
| 复数 | 实数+虚数(少用) | 2+3j、-1-2j |
2.字符串:文本的“包装”
- 定义:用单引号
' '或双引号" "包裹的文本(支持换行用''' '''或""" """)。 - 基本操作:
| 操作 | 示例 | 说明 |
|---|---|---|
| 拼接 | "你好" + "," + "小明" | 用+连接两个字符串 |
| 重复 | "哈哈" * 3 | 输出哈哈哈哈哈哈(重复3次) |
| 长度 | len("abcde") | 输出5(字符个数) |
| 索引(取字符) | "Python"[0] | 输出P(索引从0开始) |
| 切片(截取子串) | "abcdef"[1:4] | 输出bcd(索引1到3,不包含4) |
小技巧:用f-string格式化字符串(更简洁):
name = "小红"
age = 18
print(f"我是{name},今年{age}岁。") # 输出:我是小红,今年18岁。
3.字符编码:文本的“翻译规则”
- ASCII:早期只支持英文(如
A=65,a=97)。 - Unicode:全球通用编码(支持中文、日文等,如
中=20013)。 - 注意:Python3默认用Unicode,字符串存的是字符,打印时自动转成对应编码。
四、运算符:数据的“计算规则”
1.数学运算符(加减乘除)
| 符号 | 说明 | 示例 | 结果 |
|---|---|---|---|
+ | 加法 | 3 + 5 | 8 |
- | 减法 | 10 - 4 | 6 |
* | 乘法 | 2 * 6 | 12 |
/ | 除法(结果浮点数) | 8 / 2 | 4.0 |
// | 整除(取整数部分) | 7 // 2 | 3 |
% | 取余(余数) | 7 % 2 | 1 |
** | 幂运算 | 2 ** 3 | 8 |
2.赋值运算符(给变量“更新值”)
| 符号 | 说明 | 示例 | 等价于 |
|---|---|---|---|
= | 直接赋值 | a = 5 | a = 5 |
+= | 加后赋值 | a += 3 | a = a + 3 |
-= | 减后赋值 | a -= 2 | a = a - 2 |
*= | 乘后赋值 | a *= 4 | a = a * 4 |
3.比较运算符(判断“是否成立”)
返回True(真)或False(假):
| 符号 | 说明 | 示例 | 结果(假设a=5) |
|---|---|---|---|
== | 等于 | a == 5 | True |
!= | 不等于 | a != 3 | True |
> | 大于 | a > 4 | True |
< | 小于 | a < 6 | True |
>= | 大于等于 | a >= 5 | True |
<= | 小于等于 | a <= 5 | True |
4.逻辑运算符(组合判断)
| 符号 | 说明 | 示例 | 结果(假设a=5, b=3) |
|---|---|---|---|
and | 同时满足(且) | a>4 and b<5 | True(5>4且3<5) |
or | 满足一个(或) | a>10 or b<5 | True(3<5) |
not | 取反 | not (a==5) | False(a确实是5) |
5.运算符优先级(从高到低)
括号 > 幂运算 > 数学运算符 > 比较运算符 > 逻辑运算符
示例:3 + 5 * 2 ** 2 → 先算2**2=4,再算5 * 4=20,最后3+20=23。
五、应用案例:动手试试!
案例1:华氏温度转摄氏温度
公式:摄氏温度 = (华氏温度 - 32) × 5/9
步骤:
- 用
input获取用户输入的华氏温度(字符串); - 转成浮点数;
- 代入公式计算;
- 输出结果(保留2位小数)
fahrenheit = float(input("请输入华氏温度:")) # 输入:86
celsius = (fahrenheit - 32) * 5 / 9
print(f"{fahrenheit}华氏度 = {celsius:.2f}摄氏度") # 输出:86.0华氏度 = 30.00摄氏度
案例2:输入圆的半径,计算周长和面积
公式:周长=2×π×半径,面积=π×半径²(π取3.1416)
步骤:
- 输入半径(转成浮点数);
- 计算周长和面积;
- 输出结果(保留2位小数)。
radius = float(input("请输入圆的半径:")) # 输入:3
pi = 3.1416
perimeter = 2 * pi * radius
area = pi * radius ** 2
print(f"周长:{perimeter:.2f},面积:{area:.2f}") # 输出:周长:18.85,面积:28.27
案例3:输入年份,判断是否是闰年
规则:能被4整除但不能被100整除,或能被400整除的年份是闰年。
步骤:
- 输入年份(转成整数);
- 用
if-elif-else判断; - 输出结果。
year = int(input("请输入年份:")) # 输入:2024
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
print(f"{year}年是闰年!")
else:
print(f"{year}年不是闰年!") # 输出:2024年是闰年!
Day-02总结:
今天学了计算机的底层逻辑(进制)、变量的使用(存数据)、基础数据类型(数字/字符串)、运算符(计算规则),最后通过3个小项目练手。多敲代码,动手验证才能记得牢!
Python 学习笔记(第3天)--分支结构
分支结构是编程中根据条件选择执行路径的核心逻辑,就像做选择题:“如果满足A条件,就做X;否则做Y”。掌握它后,程序就能“聪明”地应对不同情况啦!
一、分支结构的核心概念
1. 关键组成
- 条件:一个能判断真假的表达式(如
age >= 18、score > 90),结果为True(真)或False(假)。 - 缩进:Python 中用缩进(通常是4个空格)表示“属于同一代码块”的代码(条件满足时要执行的操作)。
- 代码块:缩进相同的连续代码行(如条件成立时要执行的多个语句)。
2. 流程图表示(用图形理清逻辑)
分支结构常用菱形判断框表示条件,箭头指向不同路径。例如 if-else 的流程图:
开始 → 判断条件? → 是 → 执行代码块1 → 结束
↓否
执行代码块2 → 结束
Python 分支结构笔记(新手友好版)
分支结构是编程中根据条件选择执行路径的核心逻辑,就像做选择题:“如果满足A条件,就做X;否则做Y”。掌握它后,程序就能“聪明”地应对不同情况啦!
一、分支结构的核心概念
1. 关键组成
- 条件:一个能判断真假的表达式(如
age >= 18、score > 90),结果为True(真)或False(假)。 - 缩进:Python 中用缩进(通常是4个空格)表示“属于同一代码块”的代码(条件满足时要执行的操作)。
- 代码块:缩进相同的连续代码行(如条件成立时要执行的多个语句)。
2. 流程图表示(用图形理清逻辑)
分支结构常用菱形判断框表示条件,箭头指向不同路径。例如 if-else 的流程图:
复制
开始 → 判断条件? → 是 → 执行代码块1 → 结束
↓否
执行代码块2 → 结束
二、if 语句的四种形式
1. 简单 if(单分支)
场景:只需要判断一个条件,满足时执行某段代码(不满足时不处理)。
格式:
if 条件:
# 条件为 True 时执行的代码块(缩进!)
例子:判断是否成年
age = 19
if age >= 18:
print("已成年,可以进入网吧。") # 缩进的代码块
print("检查结束。") # 不缩进,无论条件是否满足都会执行
输出:
已成年,可以进入网吧。
检查结束。
2. if-else(双分支)
场景:条件满足时做A,不满足时做B(二选一)。
格式:
if 条件:
# 条件为 True 时执行的代码块
else:
# 条件为 False 时执行的代码块
例子:判断是否及格
score = 75
if score >= 60:
print("成绩及格!")
else:
print("成绩不及格,需要补考。")
输出:
成绩及格!
3. if-elif-else(多分支)
场景:有多个条件需要依次判断(比如成绩分等级:A/B/C/D),满足第一个条件后不再检查后续条件。
格式:
if 条件1:
# 条件1为 True 时执行
elif 条件2: # elif 是 "else if" 的缩写
# 条件1不满足但条件2满足时执行
elif 条件3:
# 条件1、2不满足但条件3满足时执行
else:
# 所有条件都不满足时执行(可选)
例子:百分制成绩转等级
score = 85
if score >= 90:
grade = "A"
elif score >= 80: # 80≤score<90
grade = "B"
elif score >= 70: # 70≤score<80
grade = "C"
elif score >= 60: # 60≤score<70
grade = "D"
else:
grade = "不及格"
print(f"成绩等级:{grade}") # 输出:成绩等级:B
4. 嵌套 if(多层条件)
场景:在一个条件内部再嵌套另一个条件(比如“如果是会员且积分≥1000,才能打折”)。
格式:
if 外层条件:
# 外层条件满足时,再判断内层条件
if 内层条件:
# 内外层都满足时执行
else:
# 外层满足但内层不满足时执行
else:
# 外层不满足时执行
例子:会员折扣判断
is_member = True
points = 1500
if is_member: # 先判断是否是会员
if points >= 1000: # 会员且积分足够
print("享受8折优惠!")
else:
print("会员无折扣。")
else:
print("非会员,不打折。")
输出:
享受8折优惠!
三、分支结构应用案例
案例1:用户身份验证(简单if-else)
需求:输入用户名和密码,验证是否正确(假设正确用户名为 "admin",密码为 "123456")。
username = input("请输入用户名:")
password = input("请输入密码:")
if username == "admin" and password == "123456":
print("登录成功!欢迎回来~")
else:
print("用户名或密码错误!")
案例2:英制单位与公制单位互换(if-elif)
需求:输入身高(英尺),转换为厘米(1英尺=30.48厘米);或输入体重(磅),转换为千克(1磅=0.453592千克)。
unit = input("请输入单位(英尺/磅):").strip() # strip()去除输入的空格
value = float(input("请输入数值:"))
if unit == "英尺":
cm = value * 30.48
print(f"{value}英尺 = {cm:.2f}厘米")
elif unit == "磅":
kg = value * 0.453592
print(f"{value}磅 = {kg:.2f}千克")
else:
print("输入的单位不支持!")
案例3:掷骰子决定做什么(嵌套if)
需求:掷一个骰子(1-6点),根据点数决定活动:
- 1点:看书
- 2点:听音乐
- 3点:运动
- 4点:打游戏
- 5点:学Python
- 6点:休息
import random # 导入随机数模块
dice = random.randint(1, 6) # 生成1-6的随机整数
print(f"骰子点数:{dice}")
if dice <= 3: # 1-3点
if dice == 1:
print("今天看书吧~")
else: # 2或3点
print("放松一下,听音乐!")
else: # 4-6点
if dice == 5:
print("学Python,冲鸭!")
else: # 4或6点
print("累了,休息一会儿~")
案例4:输入三条边,判断能否构成三角形并计算面积(复杂条件)
需求:输入三条边的长度,判断是否能构成三角形(任意两边之和大于第三边),若可以则计算面积(海伦公式)。
a = float(input("请输入第一条边:"))
b = float(input("请输入第二条边:"))
c = float(input("请输入第三条边:"))
# 先判断能否构成三角形
if a + b > c and a + c > b and b + c > a:
# 计算半周长
s = (a + b + c) / 2
# 海伦公式计算面积
area = (s * (s - a) * (s - b) * (s - c)) ** 0.5
print(f"可以构成三角形!面积是:{area:.2f}")
else:
print("这三条边无法构成三角形!")
注意事项
- 缩进必须统一:Python 用缩进表示代码块,同一代码块的缩进必须一致(推荐4个空格,不要用Tab键混合使用)。
- 条件顺序很重要:
if-elif-else中,条件按顺序判断,一旦某个条件满足,后面的条件不再检查(比如判断成绩等级时,>=90要放在最前面)。 - 避免“悬浮”else:
else必须和最近的if配对(缩进要对齐),否则会报错。
Day-03总结:
分支结构的核心是“根据条件选路径”,掌握 if 的四种形式(单分支、双分支、多分支、嵌套)后,就能解决大部分日常逻辑问题!多敲案例,熟悉条件表达式和缩进规则,很快就能上手~
Python 学习笔记(第4天)--循环结构
循环是编程中重复执行代码的核心工具,就像“复印机”:设定好规则后,自动重复操作。掌握它后,程序就能高效处理大量重复任务啦!
一、循环结构的核心作用
当需要多次执行同一段代码时(比如打印10次“Hello”、计算1到100的和),用循环比手动写100行代码高效得多!
二、while 循环:先判断再执行
1. 基本结构
格式:
while 条件: # 先判断条件是否为True
# 条件满足时,重复执行的代码块(缩进!)
执行流程:
先检查条件 → 条件为 True 时执行代码块 → 执行完后再次检查条件 → 重复直到条件为 False。
2. 关键语句:break 和 continue
- break:直接“跳出”整个循环,不再重复执行(相当于“结束游戏”)。
- continue:跳过当前这一次循环的剩余代码,直接进入下一次循环(相当于“跳过这一步”)。
例子1:打印1~5的数字(基础while)
num = 1 # 初始化计数器
while num <= 5: # 条件:num小于等于5时继续
print(f"当前数字:{num}")
num += 1 # 计数器+1(否则会无限循环!)
输出:
当前数字:1
当前数字:2
当前数字:3
当前数字:4
当前数字:5
例子2:用户输入验证(break+continue)
需求:让用户输入密码,直到输入正确("123")为止。
password = ""
while True: # 条件永远为True(无限循环),靠break退出
password = input("请输入密码:")
if password == "123":
print("登录成功!")
break # 输入正确,退出循环
else:
print("密码错误,重新输入!")
continue # 跳过后续代码(这里其实可以省略,因为循环会自动继续)
三、for 循环:遍历可迭代对象
1. 基本结构
格式:
for 变量 in 可迭代对象: # 遍历可迭代对象的每个元素
# 每次取一个元素,赋值给变量,执行代码块
常见可迭代对象:字符串、列表、range() 生成的数字序列等。
2. range 类型:生成数字序列
range() 是Python内置函数,用于生成连续的数字序列,常用三种形式:
range(n):生成0,1,2,...,n-1(共n个数字)。range(start, end):生成start, start+1,...,end-1(左闭右开)。range(start, end, step):生成start, start+step,...(步长为step)。
例子:用range打印1~5(两种方式)
# 方式1:用range(1,6)(start=1, end=6,不包含6)
for num in range(1, 6):
print(num) # 输出1,2,3,4,5
# 方式2:用range(5)然后+1(适合从0开始的情况)
for num in range(5):
print(num + 1) # 输出1,2,3,4,5
3. 循环中的分支结构
在 for 循环内部加 if 语句,可以筛选或处理特定元素。
例子:找出1~10中的偶数并打印
for num in range(1, 11):
if num % 2 == 0: # 偶数判断(余数为0)
print(f"{num} 是偶数")
输出:
2 是偶数
4 是偶数
6 是偶数
8 是偶数
10 是偶数
4. 嵌套循环:循环里套循环
外层循环控制“大步骤”,内层循环控制“小步骤”(比如打印乘法表时,外层控制行,内层控制列)。
例子:打印九九乘法表(嵌套for循环)
for i in range(1, 10): # 外层循环:控制行(i从1到9)
for j in range(1, i+1): # 内层循环:控制列(j从1到i)
print(f"{j}×{i}={i*j}", end="\t") # 用制表符对齐
print() # 每一行结束后换行
输出效果(前3行):
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
...(直到第9行)
5. 提前结束程序:break
在 for 循环中用 break 可以提前终止循环(比如找到目标后不再继续查找)。
例子:猜数字游戏(for+break)
需求:程序随机生成一个1~100的数,用户猜测,直到猜对为止。
import random
target = random.randint(1, 100) # 生成1-100的随机数
print("猜一个1~100的数:")
for attempt in range(1, 11): # 最多允许猜10次
guess = int(input(f"第{attempt}次猜测:"))
if guess == target:
print(f"恭喜!第{attempt}次猜对了!")
break # 猜对后提前退出循环
else: # 循环正常结束(没猜对)时执行
print(f"很遗憾,10次机会用完了!正确答案是{target}。")
四、应用案例(新手必练)
案例1:1~100求和(while vs for)
目标:计算1+2+3+…+100的和。
用while实现:
total = 0
num = 1
while num <= 100:
total += num # 累加
num += 1
print(f"1~100的和是:{total}") # 输出:5050
用for实现:
total = 0
for num in range(1, 101): # range(1,101)生成1-100
total += num
print(f"1~100的和是:{total}") # 输出:5050
案例2:判断素数(质数)
目标:输入一个数,判断是否为素数(只能被1和自身整除的大于1的自然数)。
num = int(input("请输入一个大于1的数:"))
is_prime = True # 假设是素数
if num <= 1:
is_prime = False
else:
# 检查2到num-1之间是否有因数
for i in range(2, num):
if num % i == 0:
is_prime = False
break # 找到因数,提前退出循环
print(f"{num} 是素数吗?{is_prime}")
案例3:打印三角形图案(循环控制空格和星号)
目标:打印如下三角形(高度为5行):
*
***
*****
*******
*********
height = 5
for i in range(1, height+1):
# 打印空格(每行空格数=总高度-当前行数)
print(" " * (height - i), end="")
# 打印星号(每行星号数=2*当前行数-1)
print("*" * (2*i - 1))
案例4:猴子吃桃(递推循环)
问题:猴子第一天摘了若干桃子,吃了一半多1个;第二天吃了剩下的一半多1个;……第n天剩下1个桃子。求第一天摘了多少个。
n = 10 # 假设第10天剩下1个
peach = 1 # 第n天剩下的桃子数
# 从第n天倒推回第1天
for _ in range(n-1, 0, -1): # 循环n-1次(从第9天到第1天)
peach = (peach + 1) * 2 # 前一天的桃子数 = (当天数+1)*2
print(f"第一天摘了{peach}个桃子。") # 输出:1534
案例5:百钱百鸡(多重循环)
问题:公鸡5元/只,母鸡3元/只,小鸡1元/3只。用100元买100只鸡,有多少种组合?
count = 0 # 记录符合条件的组合数
for rooster in range(0, 21): # 公鸡最多20只(5 * 20=100)
for hen in range(0, 34): # 母鸡最多33只(3 * 33=99)
chick = 100 - rooster - hen # 小鸡数量
# 小鸡数量必须是3的倍数,且总花费=100元
if chick % 3 == 0 and rooster*5 + hen*3 + chick//3 == 100:
print(f"公鸡{rooster}只,母鸡{hen}只,小鸡{chick}只")
count += 1
print(f"共有{count}种组合。") # 输出:4种
五、注意事项
- 避免死循环:
while循环必须有退出条件(比如计数器递增),否则程序会卡死! - 缩进严格:循环内的代码必须统一缩进(推荐4个空格),否则会报错。
- range的结束值:
range(1,10)生成的是1-9(不包含10),别漏掉最后一个数! - break的位置:
break只能退出当前最内层的循环,不能直接跳出多层嵌套循环
Day-04总结:循环的核心是“重复执行”,while 适合“不确定次数”的循环(靠条件控制),for 适合“遍历已知序列”的循环(靠 range 或列表控制)。多敲案例,熟悉 break 和 continue 的用法,循环结构就能轻松掌握~
Python 学习笔记(第5天)--构造程序逻辑
案例1:水仙花数(三位数的自幂数)
核心概念:水仙花数是指一个 3 位数,其各位数字的立方和等于该数本身。
(例如:153 = 1³ + 5³ + 3³ → 是水仙花数)
解题步骤:
- 遍历所有 3 位数(100-999);
- 拆分出个位、十位、百位数字;
- 计算各位数字的立方和;
- 判断立方和是否等于原数,符合则是水仙花数。
代码示例:
# 找出所有 3 位水仙花数
for num in range(100, 1000):
# 拆分各位数字(百位= num//100,十位= (num//10)%10,个位= num%10)
hundred = num // 100
ten = (num // 10) % 10
one = num % 10
# 计算立方和
cube_sum = hundred**3 + ten**3 + one**3
# 判断是否是水仙花数
if cube_sum == num:
print(f"找到水仙花数:{num}")
输出结果:
153, 370, 371, 407(这四个是 3 位水仙花数)
案例2:百钱百鸡(不定方程问题)
核心概念:用 100 元买 100 只鸡,公鸡 5 元/只,母鸡 3 元/只,小鸡 1 元 3 只。求所有可能的购买组合。
解题步骤:
- 设公鸡数量为
x,母鸡为y,小鸡为z; - 列方程:
x + y + z = 100(总数量),5x + 3y + z/3 = 100(总价格); - 简化方程得:
z = 100 - x - y,代入价格方程后可得y = (100 - 7x)/4; - 遍历
x的可能值(0 ≤ x ≤ 20,因 5x ≤ 100),筛选y和z为整数的解。
代码示例:
# 百钱百鸡所有可能组合
for x in range(0, 21): # 公鸡最多20只(5 * 20=100元)
# 母鸡数量需满足 (100-7x) 能被4整除,且结果非负
if (100 - 7 * x) % 4 != 0:
continue # 不符合条件跳过
y = (100 - 7 * x) // 4 # 母鸡数量
z = 100 - x - y # 小鸡数量
# 小鸡数量必须是3的倍数(因1元3只)
if z % 3 == 0 and z >= 0:
print(f"公鸡{x}只,母鸡{y}只,小鸡{z}只")
输出结果(部分):
公鸡0只,母鸡25只,小鸡75只
公鸡4只,母鸡18只,小鸡78只
公鸡8只,母鸡11只,小鸡81只
公鸡12只,母鸡4只,小鸡84只
案例3:Craps赌博游戏(骰子游戏)
核心规则:
- 第一次掷骰子:和为7或11 → 赢;和为2、3、12 → 输;其他和记为“点数”(如8)。
- 后续掷骰子:直到掷出“点数”则赢,掷出7则输。
解题步骤:
- 用随机数模拟骰子(1-6点,两个骰子和为2-12);
- 第一次掷骰子判断输赢;
- 若进入“点数”模式,循环掷骰子直到出现点数或7。
代码示例:
import random
def craps_game():
# 第一次掷骰子
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
first_sum = dice1 + dice2
print(f"第一次掷骰子:{dice1}+{dice2}={first_sum}")
# 判断第一次结果
if first_sum in [7, 11]:
return "赢!"
elif first_sum in [2, 3, 12]:
return "输!"
else:
point = first_sum # 记录点数
print(f"进入点数模式,目标点数:{point}")
# 循环掷骰子直到出现点数或7
while True:
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
current_sum = dice1 + dice2
print(f"再次掷骰子:{dice1}+{dice2}={current_sum}")
if current_sum == point:
return "赢!"
elif current_sum == 7:
return "输!"
# 测试游戏(运行1次)
print(craps_game())
示例输出:
第一次掷骰子:3+5=8 → 进入点数模式,目标点数:8
再次掷骰子:2+6=8 → 赢!
二、练习题目(新手必练)
题目1:斐波那契数列(前n项)
任务:生成斐波那契数列的前n项(前两项为0和1,之后每项是前两项之和)。
示例:n=5 → [0, 1, 1, 2, 3]
代码思路:
用列表存储数列,初始为 [0, 1],循环计算后续项直到达到n项。
参考代码:
def fibonacci(n):
fib = [0, 1] # 前两项
if n <= 2:
return fib[:n] # 不足2项直接返回前n项
for i in range(2, n):
next_num = fib[i-1] + fib[i-2]
fib.append(next_num)
return fib
print(fibonacci(10)) # 输出前10项:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
题目2:完美数(真因子和等于自身)
任务:找出1000以内的所有完美数(真因子指除了自身外的所有因子)。
示例:6的真因子是1、2、3,1+2+3=6 → 是完美数。
代码思路:
对每个数n,遍历1到n//2找因子,求和后判断是否等于n(优化:只需遍历到√n)。
参考代码:
def find_perfect_numbers(limit):
perfect = []
for num in range(2, limit+1):
factor_sum = 1 # 1是所有数的真因子(除了1本身)
# 遍历到平方根优化(例如6的因子1,2,3,遍历到√6≈2即可)
for i in range(2, int(num**0.5)+1):
if num % i == 0:
factor_sum += i
if i != num // i: # 避免重复加(如6的2和3)
factor_sum += num // i
if factor_sum == num:
perfect.append(num)
return perfect
print(find_perfect_numbers(1000)) # 输出:[6, 28, 496]
题目3:素数判断(质数)
任务:判断一个数是否为素数(只能被1和自身整除的大于1的自然数)。
示例:7是素数(只能被1和7整除),8不是(能被2整除)。
代码思路:
若数n小于2则不是素数;遍历2到√n,若有能整除的数则不是素数。
参考代码:
def is_prime(num):
if num < 2:
return False
# 遍历2到平方根(优化:减少循环次数)
for i in range(2, int(num**0.5)+1):
if num % i == 0:
return False
return True
# 测试
print(is_prime(7)) # True
print(is_prime(15)) # False
print(is_prime(97)) # True(97是素数)
Day-05 总结:新手学习技巧
- 先理解逻辑,再写代码:比如水仙花数,先想清楚“如何拆分各位数”再动手。
- 用具体例子验证:写完代码后,用已知结果(如水仙花数153)测试是否正确。
- 注释每一步:代码中加注释说明“这一步在做什么”,方便复习。
- 从简单版开始:比如斐波那契数列,先写前5项,再扩展到n项。
Python 学习笔记(第6天)--函数和模块的使用
一、函数:代码的「万能工具包」
作用:避免重复代码(代码的「坏味道」),让程序更清晰、易维护!
比如:你想计算10次圆面积,每次都写一遍公式?用函数封装后,调用10次即可~
二、定义函数:给功能起个「名字」
用 def 关键字定义函数,格式:
def 函数名(参数列表):
函数体(具体操作)
return 返回值 # 可选(没有return默认返回None)
例子:写一个加法函数
def add(a, b): # a和b是参数
result = a + b
return result # 返回计算结果
三、调用函数:让工具「跑起来」
函数定义后,需要「调用」才能执行。调用方式分两种:
-
内置函数:Python自带的函数(如
print()、len())。
例:print("你好")→ 输出「你好」;len("abc")→ 返回3(字符串长度)。 -
自定义函数:自己写的函数。
例:调用上面的add函数
sum_result = add(3, 5) # 传入参数3和5
print(sum_result) # 输出8(函数返回的结果)
四、参数:函数的「输入接口」
函数可以接收不同类型的参数,灵活应对各种需求:
| 参数类型 | 特点 | 例子 |
|---|---|---|
| 默认参数 | 参数有默认值,调用时可选填 | def greet(name="客人"): → 调用 greet() 输出「你好,客人」;greet("小明") 输出「你好,小明」 |
| 可变参数 | 接收任意数量的参数(元组形式) | def sum_numbers(*args): → 调用 sum_numbers(1,2,3) → 计算1+2+3=6 |
| 关键字参数 | 用 参数名=值 传递,明确对应关系(避免顺序错误) | def person(name, age): → 调用 person(age=20, name="张三") → 正确赋值 |
| 命名关键字参数 | 限制参数必须用指定名字传递(防止漏传) | def func(*, a, b): → 调用 func(a=1, b=2)(不能省略参数名) |
五、返回值:函数的「输出结果」
函数可以用 return 返回结果,支持返回单个值或多个值(元组形式):
-
无返回值:没写
return或return None(默认)。
例:def say_hello(): print("Hello")→ 调用后无结果,仅执行打印。 -
返回单个值:返回一个数据。
例:def square(x): return x**2→ 调用square(3)→ 返回9。 -
返回多个值:返回元组(可解包接收)。
例:def get_info(): return "张三", 20→ 调用name, age = get_info()→ name="张三", age=20。
六、作用域:变量的「活动范围」
变量只能在特定范围内使用,常见作用域规则:
| 作用域类型 | 说明 |
|---|---|
| 局部作用域 | 函数内部定义的变量,仅在函数内有效 |
| 全局作用域 | 函数外定义的变量(全局变量),整个程序可用(函数内修改需 global 声明) |
| 嵌套作用域 | 嵌套函数中,内层函数可访问外层函数的变量(需 nonlocal 声明修改) |
| 内置作用域 | Python内置的变量/函数(如 print、len) |
例子:
x = 10 # 全局变量
def test():
y = 20 # 局部变量(仅在test函数内有效)
print(x) # 可以访问全局变量x → 输出10
# y = 30 # 修改局部变量y不影响外部(如果有的话)
test()
# print(y) # 报错!y是局部变量,外部无法访问
七、模块:函数的「收纳盒」
当函数太多时,把它们放到单独的 .py 文件(模块)里管理,避免代码混乱!
操作步骤:
1.创建模块:新建 math_utils.py 文件,写入自定义函数:
# math_utils.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
2.导入模块:在其他文件中用 import 导入模块或函数:
# 方式1:导入整个模块
import math_utils
print(math_utils.add(3, 5)) # 输出8
# 方式2:导入指定函数(推荐)
from math_utils import add
print(add(3, 5)) # 直接调用 → 输出8
# 方式3:重命名模块(避免命名冲突)
import math_utils as mu
print(mu.multiply(2, 3)) # 输出6
3.解决命名冲突:如果两个模块有同名函数,用模块名区分:
# 假设模块A.py和B.py都有add函数
from A import add as add_A
from B import add as add_B
print(add_A(1,2)) # 调用A模块的add
print(add_B(1,2)) # 调用B模块的add
总结(初学者必记)
- 函数是「代码复用」的核心工具,能让你写得更少、错得更少!
- 参数类型要记清:默认参数省事儿,可变参数灵活,关键字参数防错。
- 返回值可以是多个,用元组解包接收超方便~
- 模块是函数的「收纳盒」,命名冲突用
模块名.函数名解决!
动手练习:试着写一个计算圆面积的函数(def circle_area(r):),再用模块管理它~ 😊
Python 学习笔记(第7天)--字符串和常用数据结构
一、字符串:文本的「收纳盒」
字符串是Python中最常用的数据类型,用 '' 或 "" 包裹,用来存储文本。
1. 基础操作
| 操作 | 说明 | 示例 |
|---|---|---|
| 计算长度 | 用 len() 函数获取字符串字符个数 | s = "hello"; print(len(s)) → 输出5 |
| 下标运算 | 用 [索引] 访问单个字符(索引从0开始) | s = "abcde"; print(s[0]) → 'a';s[-1] → 'e'(负数从末尾开始数) |
| 切片 | 用 [start:end:step] 截取子串(左闭右开) | s = "abcdef"; print(s[1:4]) → 'bcd';s[::2] → 'ace'(步长2) |
| 常用方法 | 字符串内置方法(不修改原字符串,返回新字符串) | s = " Hello " → s.strip() → 'Hello'(去空格);s.upper() → ' HELLO '(转大写) |
例子:处理用户输入的姓名
name = input("请输入你的名字:")
print(f"你好,{name.strip()}!") # 去掉输入的首尾空格
2. 注意事项
- 字符串是不可变的!修改字符串会生成新字符串(如
s = s + "世界")。
二、列表:有序的「收纳筐」
列表用 [] 包裹,存储多个元素(可重复、可修改),是最灵活的数据结构。
1. 基本用法
| 操作 | 说明 | 示例 |
|---|---|---|
| 定义列表 | 用 [] 直接创建 | nums = [1, 2, 3]; mixed = ["a", 1, True] |
| 访问元素 | 用 [索引] 访问(索引从0开始) | nums = [10, 20, 30]; print(nums[1]) → 20 |
| 下标越界 | 索引超出范围会报错 IndexError | nums = [1,2]; nums[2] → 报错(最大索引是1) |
| 添加元素 | append() 末尾添加;insert(i, x) 插入到位置i | nums = [1,2]; nums.append(3) → [1,2,3];nums.insert(0, 0) → [0,1,2,3] |
| 删除元素 | pop() 默认删末尾;remove(x) 删第一个x;del 直接删索引 | nums = [1,2,3]; nums.pop() → 3,剩余[1,2];nums.remove(2) → [1,3] |
| 修改元素 | 直接用 [索引] = 新值 | nums = [1,2,3]; nums[0] = 10 → [10,2,3] |
| 切片 | 同字符串,返回新列表 | nums = [1,2,3,4]; print(nums[1:3]) → [2,3];nums[::-1] → [4,3,2,1](反转) |
| 循环遍历 | 用 for 逐个访问元素 | fruits = ["苹果", "香蕉"]; for fruit in fruits: print(fruit) → 输出两行水果名 |
例子:统计班级成绩
scores = [85, 92, 78, 95, 88]
print("最高分:", max(scores)) # 95
print("平均分:", sum(scores)/len(scores)) # (85+92+78+95+88)/5=87.6
2. 常用操作
| 操作 | 说明 | 示例 |
|---|---|---|
| 连接 | + 合并列表;extend() 原地合并 | a = [1,2]; b = [3,4]; c = a + b → [1,2,3,4];a.extend(b) → a变为[1,2,3,4] |
| 复制 | 浅拷贝(copy() 或切片 [:]);深拷贝(需用 copy.deepcopy()) | a = [1, [2,3]]; b = a.copy(); b[0] = 10 → a还是[1,[2,3]](浅拷贝不影响嵌套列表) |
| 长度 | len() 获取元素个数 | nums = [1,2,3]; len(nums) → 3 |
| 排序 | sort() 原地排序(默认升序);sorted() 返回新排序列表 | nums = [3,1,2]; nums.sort() → [1,2,3];new_nums = sorted(nums, reverse=True) → [3,2,1] |
| 倒转 | reverse() 原地反转;切片 [::-1] 返回新反转列表 | nums = [1,2,3]; nums.reverse() → [3,2,1];nums[::-1] → [3,2,1](原列表不变) |
| 查找 | in 判断是否存在;index() 找第一个匹配的索引 | fruits = ["苹果", "香蕉"]; "苹果" in fruits → True;fruits.index("香蕉") → 1 |
3. 生成列表
| 方法 | 说明 | 示例 |
|---|---|---|
| range创建数字列表 | range(start, end, step) 生成数字序列,转列表用 list() | nums = list(range(5)) → [0,1,2,3,4];nums = list(range(2, 10, 2)) → [2,4,6,8] |
| 生成表达式 | [表达式 for 变量 in 可迭代对象](简洁生成列表) | squares = [x**2 for x in range(5)] → [0,1,4,9,16] |
| 生成器 | (表达式 for 变量 in 可迭代对象)(节省内存,按需生成) | gen = (x*2 for x in range(3)); print(next(gen)) → 0;print(next(gen)) → 2 |
三、元组:不可变的「有序盒」
元组用 () 包裹,元素不可修改(不可变列表),适合存储固定数据。
1. 基本用法
| 操作 | 说明 | 示例 |
|---|---|---|
| 定义元组 | 用 () 或直接写(单个元素需加逗号) | t = (1, 2, 3); t2 = 4,(合法);t3 = (5,)(单个元素元组) |
| 访问元素 | 同列表,用 [索引] | t = ("a", "b"); print(t[0]) → 'a' |
| 修改元组变量 | 元组本身不可变,但可以重新赋值整个变量 | t = (1,2); t = (3,4) → 现在t是(3,4) |
| 元组与列表转换 | tuple() 列表转元组;list() 元组转列表 | lst = [1,2]; tpl = tuple(lst) → (1,2);lst2 = list(tpl) → [1,2] |
四、集合:无序的「唯一盒」
集合用 {} 包裹(空集合用 set()),元素唯一、无序,适合去重或快速查找。
1. 基本用法
| 操作 | 说明 | 示例 |
|---|---|---|
| 创建集合 | set() 或 {元素1, 元素2...}(空集合不能用 {}) | s = {1, 2, 3}; s2 = set([1,2,3])(列表转集合) |
| 添加元素 | add(x) 添加单个元素;update([x,y]) 添加多个元素 | s = {1,2}; s.add(3) → {1,2,3};s.update([4,5]) → {1,2,3,4,5} |
| 删除元素 | remove(x) 删指定元素(不存在报错);discard(x) 删指定元素(不存在不报错);clear() 清空 | s = {1,2,3}; s.remove(2) → {1,3};s.discard(10) → 无变化;s.clear() → set() |
| 清空集合 | clear() 方法 | s = {1,2}; s.clear() → set() |
2. 常用操作
| 操作 | 说明 | 示例 |
|---|---|---|
| 交集 | 两个集合都有的元素(& 或 intersection()) | a = {1,2,3}; b = {2,3,4}; print(a & b) → {2,3} |
| 并集 | 两个集合所有元素(` | 或union()`) |
| 差集 | 在a中但不在b中的元素(- 或 difference()) | a - b → {1} |
| 对称差 | 仅在a或仅在b中的元素(^ 或 symmetric_difference()) | a ^ b → {1,4} |
| 子集 | a是b的子集(<= 或 issubset()) | {1,2} <= {1,2,3} → True |
| 超集 | a是b的超集(>= 或 issuperset()) | {1,2,3} >= {1,2} → True |
五、字典:键值对的「字典」
字典用 {} 包裹,存储 键: 值 对(键唯一、不可变),适合快速查找数据。
1. 基本用法
| 操作 | 说明 | 示例 |
|---|---|---|
| 创建字典 | {键1: 值1, 键2: 值2...} | info = {"name": "张三", "age": 20} |
| 添加元素 | 直接赋值 字典[键] = 值 | info["score"] = 90 → info变为{"name":"张三", "age":20, "score":90} |
| 删除元素 | del 字典[键] 或 pop(键)(返回值) | del info["age"] → 删除age键;score = info.pop("score") → score=90 |
| 取值 | 字典[键](键不存在报错);get(键, 默认值)(键不存在返回默认值) | name = info["name"] → "张三";gender = info.get("gender", "未知") → "未知" |
| 清空字典 | clear() 方法 | info.clear() → {} |
2. 常用操作
| 操作 | 说明 | 示例 |
|---|---|---|
| keys() | 获取所有键(返回类似列表的对象) | info = {"a":1, "b":2}; keys = info.keys() → dict_keys(['a', 'b']) |
| values() | 获取所有值 | values = info.values() → dict_values([1,2]) |
| items() | 获取所有键值对(返回 (键, 值) 元组列表) | items = info.items() → dict_items([('a',1), ('b',2)]) |
| setdefault() | 若键不存在,设置默认值(存在则不修改) | info.setdefault("age", 18) → info变为{"a":1, "b":2, "age":18} |
六、基础练习(动手试试!)
1.跑马灯效果:用字符串切片实现循环滚动显示 hello(如 elloh → llohe...)。
s = "hello"
for i in range(len(s)):
print(s[i:] + s[:i])
2.列表找最大元素:用 max() 函数找出 [3, 7, 2, 9, 4] 中的最大值。
3.统计考试成绩平均分:输入5个成绩(用 input().split() 获取),计算平均值。
scores = list(map(int, input("请输入5个成绩(空格分隔):").split()))
avg = sum(scores) / len(scores)
print(f"平均分:{avg}")
4.Fibonacci数列:生成前10项(1, 1, 2, 3, 5...)。
a, b = 1, 1
fib = [a, b]
for _ in range(8):
a, b = b, a + b
fib.append(b)
print(fib)
5.杨辉三角:打印前5行(每行两端是1,中间是上一行两数之和)。
for i in range(5):
row = [1]*(i+1)
for j in range(1, i):
row[j] = row[j-1] + row[j+1]
print(row)
七、综合案例(实战上手!)
案例1:双色球选号
需求:随机生成6个红球(1-33,不重复)和1个蓝球(1-16)。
import random
# 选红球(去重)
red = []
while len(red) < 6:
num = random.randint(1, 33)
if num not in red:
red.append(num)
red.sort() # 排序
# 选蓝球
blue = random.randint(1, 16)
print(f"红球:{red},蓝球:{blue}")
案例2:井字棋游戏
需求:两人轮流在3x3棋盘落子,先连成直线(横/竖/斜)者胜。
# 初始化棋盘(用二维列表)
board = [[" " for _ in range(3)] for _ in range(3)]
def print_board():
for row in board:
print("|".join(row))
print("-" * 5)
# 游戏主循环
current_player = "X"
while True:
print_board()
print(f"玩家 {current_player} 下棋:")
x = int(input("行(0-2):"))
y = int(input("列(0-2):"))
# 检查位置是否合法
if board[x][y] != " ":
print("该位置已被占用!")
continue
# 落子
board[x][y] = current_player
# 检查是否胜利(简单示例)
if (board[x][0] == board[x][1] == board[x][2] == current_player or # 行
board[0][y] == board[1][y] == board[2][y] == current_player or # 列
(x == y and board[0][0] == board[1][1] == board[2][2] == current_player) or # 左上到右下
(x + y == 2 and board[0][2] == board[1][1] == board[2][0] == current_player)): # 右上到左下
print_board()
print(f"玩家 {current_player} 获胜!")
break
# 切换玩家
current_player = "O" if current_player == "X" else "X"
总结(初学者必记)
- 字符串:文本处理用
len()、切片、upper()等方法。 - 列表:可变、有序,用
append()、pop()、sort()管理元素。 - 元组:不可变,适合存储固定数据(如坐标)。
- 集合:去重、快速查找,用
&、|做交集/并集。 - 字典:键值对存储,用
get()安全取值,items()遍历键值。
动手提示:遇到问题多打印变量(print()),观察每一步结果! 😊
Python 学习笔记(第8天)--面向对象编程基础
一、类与对象:现实世界的「模板」与「实例」
核心思想:用「类」描述一类事物的共同特征(如「学生」有姓名、年龄),用「对象」表示具体的个体(如「张三」是学生类的一个对象)。
1. 关键概念
| 概念 | 说明 | 生活例子 |
|---|---|---|
| 类(Class) | 描述一类事物的「模板」(属性+方法),不占用内存 | 「学生」类:定义学生的姓名、年龄(属性),学习、吃饭(方法) |
| 对象(Object) | 类的「具体实例」(占用内存),是类的「个体」 | 张三、李四(都是「学生」类的对象) |
| 面向对象(OOP) | 以「对象」为中心的编程思想,通过对象交互解决问题 | 游戏中,玩家、怪物、道具都是对象,各自有属性(血量、攻击力)和方法(移动、攻击) |
一句话总结:类是「设计图」,对象是「根据设计图造出来的实物」。
二、定义类:给事物「建模」
用 class 关键字定义类,格式:
class 类名:
# 类属性(所有对象共享)
# 构造器(初始化对象属性)
# 实例方法(对象能做的事)
# 类方法/静态方法(可选)
1.类的核心组成
| 组成 | 说明 | 示例(学生类) |
|---|---|---|
| 实例属性 | 每个对象独有的属性(通过 self.属性名 定义) | self.name = name(每个学生的姓名不同) |
| 类属性 | 所有对象共享的属性(直接定义在类中,用 类名.属性名 访问) | class Student: school = "实验中学"(所有学生都来自同一学校) |
构造器(__init__) | 对象初始化时自动调用的方法,用于设置初始属性(必须包含 self 参数) | def __init__(self, name, age): self.name = name; self.age = age |
| 实例方法 | 对象能执行的操作(第一个参数必须是 self,指向对象自身) | def study(self): print(f"{self.name} 在学习") |
**__str__ 方法** | 定义对象的「字符串描述」(打印对象时自动调用) | def __str__(self): return f"学生({self.name}, {self.age}岁)" |
例子:定义学生类
class Student:
# 类属性(所有学生共享)
school = "实验中学"
# 构造器(初始化对象属性)
def __init__(self, name, age):
self.name = name # 实例属性(每个学生独有的姓名)
self.age = age # 实例属性(每个学生独有的年龄)
# 实例方法(学生能做的事)
def study(self):
print(f"{self.name} 正在学习Python")
# __str__ 方法(打印对象时的描述)
def __str__(self):
return f"学生信息:姓名={self.name}, 年龄={self.age}岁"
三、使用对象:让对象「动起来」
创建对象(实例化)后,通过 对象.属性 访问属性,对象.方法() 调用方法(给对象发消息)。
1. 操作步骤
-
创建对象(实例化):用
类名(参数)生成对象。
例:stu1 = Student("张三", 15)→ 创建一个叫张三、15岁的学生对象。 -
访问属性:用
对象.属性名获取或修改属性。
例:print(stu1.name)→ 输出「张三」;stu1.age = 16→ 修改年龄为16岁。 -
调用方法:用
对象.方法名()执行对象的功能。
例:stu1.study()→ 输出「张三 正在学习Python」。 -
打印对象:直接
print(对象)会调用__str__方法。
例:print(stu1)→ 输出「学生信息:姓名=张三, 年龄=15岁」。
四、面向对象的四大支柱
面向对象的核心思想是 抽象、封装、继承、多态,理解这四个概念是OOP的关键!
| 支柱 | 核心思想 | 生活例子 |
|---|---|---|
| 抽象 | 提取一类事物的共同特征(忽略细节),用类描述。 | 设计「汽车」类时,只关注「品牌、颜色、速度」等共同属性,不关心具体是轿车还是卡车 |
| 封装 | 隐藏对象的内部细节(如属性),仅暴露必要的接口(方法)。 | 手机有「充电」方法,但用户不需要知道电池如何工作(隐藏内部细节) |
| 继承 | 子类可以继承父类的属性和方法(复用代码),并可扩展新功能。 | 「大学生」类继承「学生」类(已有姓名、年龄),新增「专业」属性 |
| 多态 | 不同子类对同一方法有不同的实现(同一操作,不同对象结果不同)。 | 「狗」和「猫」都有「叫」方法,但狗叫「汪汪」,猫叫「喵喵」 |
五、基础练习:动手定义类
通过练习巩固类的定义和使用,尝试以下案例:
1. 定义时钟类
需求:时钟有小时、分钟、秒属性,能显示时间(show_time 方法),能走时(tick 方法,每秒+1)。
class Clock:
def __init__(self, hour=0, minute=0, second=0):
self.hour = hour
self.minute = minute
self.second = second
def show_time(self):
return f"{self.hour:02d}:{self.minute:02d}:{self.second:02d}" # 补零显示
def tick(self):
self.second += 1
if self.second == 60:
self.second = 0
self.minute += 1
if self.minute == 60:
self.minute = 0
self.hour += 1
if self.hour == 24:
self.hour = 0
# 使用示例
clock = Clock(12, 30, 45)
print(clock.show_time()) # 输出:12:30:45
clock.tick()
print(clock.show_time()) # 输出:12:30:46
2. 定义图形类
需求:图形有颜色属性,能计算面积(抽象方法,子类实现)。
from abc import ABC, abstractmethod # 抽象类需要导入ABC和abstractmethod
class Shape(ABC): # 抽象类(不能直接实例化)
def __init__(self, color):
self.color = color
@abstractmethod # 抽象方法(子类必须实现)
def area(self):
pass
class Circle(Shape):
def __init__(self, color, radius):
super().__init__(color) # 调用父类构造器
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2 # 圆的面积公式
# 使用示例
red_circle = Circle("红色", 5)
print(f"红色圆的颜色:{red_circle.color}") # 输出:红色圆的颜色:红色
print(f"面积:{red_circle.area()}") # 输出:面积:78.5
3. 定义汽车类
需求:汽车有品牌、速度属性,能加速(accelerate 方法)、刹车(brake 方法)。
class Car:
def __init__(self, brand, speed=0):
self.brand = brand
self.speed = speed
def accelerate(self, delta):
self.speed += delta
print(f"{self.brand} 加速,当前速度:{self.speed}km/h")
def brake(self):
self.speed = 0
print(f"{self.brand} 刹车,已停止")
# 使用示例
my_car = Car("特斯拉")
my_car.accelerate(50) # 输出:特斯拉 加速,当前速度:50km/h
my_car.accelerate(30) # 输出:特斯拉 加速,当前速度:80km/h
my_car.brake() # 输出:特斯拉 刹车,已停止
总结(初学者必记)
- 类与对象:类是模板,对象是实例(如「学生」类 → 张三、李四)。
- 类的组成:属性(数据)+ 方法(功能),构造器
__init__初始化对象。 - 四大支柱:抽象(提特征)、封装(藏细节)、继承(复用代码)、多态(不同实现)。
动手提示:自己尝试定义一个「宠物类」(属性:名字、类型;方法:叫、吃),并创建对象调用方法!
Python 学习笔记(第9天)--面向对象进阶
一、属性:类与对象的「数据仓库」
属性是类或对象存储数据的变量,分为类属性和实例属性,还可以通过访问器、修改器等控制属性的读写。
1. 类属性 vs 实例属性
| 类型 | 定义位置 | 访问方式 | 特点 | 示例(学生类) |
|---|---|---|---|---|
| 类属性 | 类内部,方法外部 | 类名.属性 或 对象.属性 | 所有对象共享同一值,修改后全局生效 | school = "实验中学"(所有学生同校) |
| 实例属性 | 构造器 __init__ 中 | 对象.属性 | 每个对象独有,不同对象值可不同 | self.name = name(张三、李四姓名不同) |
例子:
class Student:
school = "实验中学" # 类属性(所有学生共享)
def __init__(self, name, age):
self.name = name # 实例属性(每个学生独有)
self.age = age # 实例属性(每个学生独有)
# 访问类属性
print(Student.school) # 输出:实验中学
stu1 = Student("张三", 15)
print(stu1.school) # 输出:实验中学(对象也能访问类属性)
# 访问实例属性
print(stu1.name) # 输出:张三
stu2 = Student("李四", 16)
print(stu2.age) # 输出:16(与stu1的age不同)
2. 属性访问器、修改器、删除器
通过 @property、@属性名.setter、@属性名.deleter 装饰器,控制属性的读写逻辑(如验证数据有效性)。
例子:限制年龄不能为负数
class Student:
def __init__(self, name, age):
self.name = name
self.age = age # 调用age的修改器(因为用了@property)
# 访问器(读age时调用)
@property
def age(self):
return self._age # 实际存储用_age(避免与属性名冲突)
# 修改器(设置age时调用)
@age.setter
def age(self, value):
if value < 0:
raise ValueError("年龄不能为负数!")
self._age = value
# 删除器(删除age时调用)
@age.deleter
def age(self):
print("删除年龄属性!")
del self._age
# 使用示例
stu = Student("张三", 15)
print(stu.age) # 输出:15(调用访问器)
stu.age = 16 # 调用修改器(正常设置)
# stu.age = -1 # 报错:ValueError(修改器验证)
del stu.age # 调用删除器(输出:删除年龄属性!)
3. slots:限制实例属性
通过 __slots__ 可以限制类实例能添加的属性,减少内存占用(适合属性固定的类)。
例子:限制学生只能有name和age属性
class Student:
__slots__ = ("name", "age") # 只允许有name和age属性
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student("张三", 15)
stu.grade = "高三" # 报错:AttributeError(不能添加grade属性)
二、方法:对象的「行为工具箱」
方法是类中定义的函数,分为实例方法、类方法、静态方法,用途不同。
| 方法类型 | 定义参数 | 调用方式 | 作用 | 示例(学生类) |
|---|---|---|---|---|
| 实例方法 | 第一个参数是self | 对象.方法() | 操作实例属性或类属性(最常用) | def study(self): print(f"{self.name}学习") |
| 类方法 | 第一个参数是cls | 类名.方法() 或 对象.方法() | 操作类属性或创建对象(需@classmethod) | @classmethod def change_school(cls, new_school): cls.school = new_school |
| 静态方法 | 无self/cls | 类名.方法() 或 对象.方法() | 独立功能(与类/实例无关,需@staticmethod) | @staticmethod def check_age(age): return age >= 6 |
例子:三种方法的综合使用
class Student:
school = "实验中学" # 类属性
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 实例方法(操作实例属性)
def study(self):
print(f"{self.name}({self.age}岁)在{self.school}学习")
# 类方法(修改类属性)
@classmethod
def change_school(cls, new_school):
cls.school = new_school
print(f"所有学生学校改为:{new_school}")
# 静态方法(独立验证逻辑)
@staticmethod
def is_adult(age):
return age >= 18
# 使用实例方法
stu1 = Student("张三", 15)
stu1.study() # 输出:张三(15岁)在实验中学学习
# 使用类方法(修改类属性)
Student.change_school("重点中学")
stu2 = Student("李四", 16)
stu2.study() # 输出:李四(16岁)在重点中学学习
# 使用静态方法
print(Student.is_adult(17)) # 输出:False
print(Student.is_adult(20)) # 输出:True
三、运算符重载:让对象「会计算」
通过定义魔法方法(以__开头和结尾),可以让对象支持加减、比较、长度计算等运算符操作。
| 魔法方法 | 对应操作 | 说明 | 示例(分数类) |
|---|---|---|---|
__add__(self, other) | 对象1 + 对象2 | 定义加法逻辑 | 分数相加:1/2 + 1/3 = 5/6 |
__sub__(self, other) | 对象1 - 对象2 | 定义减法逻辑 | 分数相减:1/2 - 1/3 = 1/6 |
__len__(self) | len(对象) | 定义对象的长度 | 字符串长度、列表长度 |
__repr__(self) | print(对象) 或 repr(对象) | 定义对象的「官方」字符串表示 | 分数1/2显示为"1/2" |
__eq__(self, other) | 对象1 == 对象2 | 定义相等判断逻辑 | 1/2 == 2/4 返回True |
__contains__(self, item) | item in 对象 | 定义成员关系判断(如in操作) | 判断"abc"是否在"abcdef"中 |
例子:自定义分数类(支持加减、比较)
class Fraction:
def __init__(self, numerator, denominator):
self.numerator = numerator # 分子
self.denominator = denominator # 分母(不为0)
# 加法:1/2 + 1/3 = (1 * 3 + 1 * 2)/(2 * 3) = 5/6
def __add__(self, other):
new_num = self.numerator * other.denominator + other.numerator * self.denominator
new_den = self.denominator * other.denominator
return Fraction(new_num, new_den)
# 相等判断:1/2 == 2/4 → 分子分母同乘后相等
def __eq__(self, other):
return self.numerator * other.denominator == other.numerator * self.denominator
# 官方字符串表示:1/2 → "1/2"
def __repr__(self):
return f"{self.numerator}/{self.denominator}"
# 使用示例
f1 = Fraction(1, 2)
f2 = Fraction(1, 3)
f3 = f1 + f2
print(f3) # 输出:5/6(调用__repr__)
print(f1 == Fraction(2, 4)) # 输出:True(调用__eq__)
四、类之间的关系:对象间的「互动规则」
类之间通过关联、继承、依赖建立联系,理解这些关系是设计复杂程序的基础。
| 关系类型 | 定义 | 示例 |
|---|---|---|
| 关联 | 对象之间长期稳定的合作关系(如A有一个B) | 学生(A)有一个书包(B)→ student.bag = bag |
| 继承 | 子类继承父类的属性和方法(复用+扩展) | 大学生(子类)继承学生(父类),新增「专业」属性 |
| 依赖 | 对象A的方法需要对象B作为参数(临时使用) | 学生(A)的learn_from(teacher)方法需要教师(B)对象 |
五、继承与多态:代码复用的「终极武器」
继承让子类复用父类代码,多态让不同子类对同一方法有不同实现。
1. 继承的核心操作
- 语法:
class 子类(父类):(支持多继承,如class 子类(父1, 父2):)。 - 调用父类方法:用
super().方法名()调用父类方法(避免递归)。 - 方法重写:子类重新定义父类已有的方法(覆盖父类逻辑)。
- 类型判定:
isinstance(对象, 类)判断对象是否是某类实例;issubclass(子类, 父类)判断是否是子类。
例子:学生类 → 大学生类(继承+方法重写)
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print(f"{self.name} 在学习")
class CollegeStudent(Student): # 继承Student类
def __init__(self, name, age, major):
super().__init__(name, age) # 调用父类构造器(初始化name和age)
self.major = major # 新增属性:专业
def study(self): # 方法重写(覆盖父类的study)
print(f"{self.name}({self.major}专业) 在学习专业课程")
# 类型判定
stu = CollegeStudent("张三", 20, "计算机")
print(isinstance(stu, CollegeStudent)) # 输出:True(是大学生类实例)
print(issubclass(CollegeStudent, Student)) # 输出:True(大学生是学生的子类)
2. 多重继承与菱形继承
- 多重继承:子类继承多个父类(如
class A(B, C):)。 - 菱形继承:子类继承的两个父类有共同父类(形成菱形结构),可能导致方法冲突。Python用C3算法确定方法查找顺序(优先找子类→左父类→右父类→共同父类)。
例子:菱形继承(C3算法)
class A:
def func(self):
print("A的func")
class B(A):
pass # 继承A的func
class C(A):
def func(self):
print("C的func") # 重写A的func
class D(B, C): # D的父类是B和C(B的父类是A,C的父类是A)
pass
d = D()
d.func() # 输出:C的func(C3顺序:D→B→C→A,优先找C的func)
六、综合案例:贴近生活的实战
案例1:工资结算系统
需求:不同员工类型(全职、兼职)计算工资。
class Employee:
def __init__(self, name):
self.name = name
def calculate_salary(self):
raise NotImplementedError("子类必须实现calculate_salary方法")
class FullTimeEmployee(Employee):
def __init__(self, name, monthly_salary):
super().__init__(name)
self.monthly_salary = monthly_salary
def calculate_salary(self): # 重写父类方法
return self.monthly_salary # 全职按月薪发放
class PartTimeEmployee(Employee):
def __init__(self, name, hours, rate):
super().__init__(name)
self.hours = hours # 工作时长
self.rate = rate # 时薪
def calculate_salary(self): # 重写父类方法
return self.hours * self.rate # 兼职按时薪×时长发放
# 使用示例
full = FullTimeEmployee("张三", 15000)
part = PartTimeEmployee("李四", 100, 200)
print(f"{full.name}工资:{full.calculate_salary()}元") # 输出:张三工资:15000元
print(f"{part.name}工资:{part.calculate_salary()}元") # 输出:李四工资:20000元
案例2:图书自动折扣系统
需求:不同会员等级享受不同折扣(普通会员无折扣,VIP会员9折)。
class Member:
def __init__(self, name, level="普通"):
self.name = name
self.level = level
def get_discount(self):
if self.level == "VIP":
return 0.9 # VIP打9折
else:
return 1.0 # 普通无折扣
class Book:
def __init__(self, price):
self.price = price # 原价
def calculate_final_price(self, member):
discount = member.get_discount() # 依赖Member的折扣逻辑
return self.price * discount
# 使用示例
vip_member = Member("张三", "VIP")
normal_member = Member("李四")
book = Book(100)
print(f"VIP购买价格:{book.calculate_final_price(vip_member)}元") # 输出:90.0元
print(f"普通购买价格:{book.calculate_final_price(normal_member)}元") # 输出:100.0元
案例3:自定义分数类(进阶)
需求:支持分数加减、比较、字符串显示。
class Fraction:
def __init__(self, numerator, denominator=1):
if denominator == 0:
raise ValueError("分母不能为0!")
# 约分(最大公约数)
gcd = self.gcd(numerator, denominator)
self.numerator = numerator // gcd
self.denominator = denominator // gcd
if self.denominator < 0: # 分母保持正数
self.numerator *= -1
self.denominator *= -1
@staticmethod
def gcd(a, b):
while b:
a, b = b, a % b
return a
def __add__(self, other):
new_num = self.numerator * other.denominator + other.numerator * self.denominator
new_den = self.denominator * other.denominator
return Fraction(new_num, new_den)
def __eq__(self, other):
return self.numerator == other.numerator and self.denominator == other.denominator
def __repr__(self):
return f"{self.numerator}/{self.denominator}"
# 使用示例
f1 = Fraction(1, 2)
f2 = Fraction(1, 3)
print(f1 + f2) # 输出:5/6(自动约分)
print(Fraction(2, 4)) # 输出:1/2(自动约分)
print(f1 == Fraction(2, 4)) # 输出:True(相等判断)
七、总结(初学者必记)
- 属性:类属性共享,实例属性独有;用
@property控制读写。 - 方法:实例方法操作实例,类方法操作类,静态方法独立功能。
- 运算符重载:通过魔法方法让对象支持加减、比较等操作。
- 继承与多态:子类复用父类代码,重写方法实现多态。
动手提示:尝试用面向对象设计一个「宠物医院系统」(宠物类、医生类、就诊记录类),实践类之间的关系和继承! 😊
Python 学习笔记(第10天)--图形用户界面和游戏开发
一、Tkinter:快速开发桌面GUI程序
Tkinter 是 Python 内置的 GUI 库(无需额外安装),适合开发轻量级桌面应用(如计算器、备忘录、设置工具等)。
1. Tkinter 核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 主窗口 | 程序的入口,所有组件都放在主窗口中 | root = tk.Tk();root.title("我的第一个GUI") |
| 组件(Widget) | 界面元素(按钮、标签、输入框等) | tk.Button(root, text="点击我");tk.Entry(root) |
| 布局管理器 | 控制组件在窗口中的位置(pack/grid/place) | button.pack()(垂直排列);label.grid(row=0, column=0)(网格布局) |
| 事件绑定 | 给组件绑定点击、输入等事件的处理函数 | button.config(command=click_handler) |
2. 快速上手:做一个「待办事项」工具
目标:输入待办事项,点击按钮添加到列表,支持删除。
代码示例
import tkinter as tk
from tkinter import messagebox
class TodoApp:
def __init__(self, root):
self.root = root
self.root.title("待办事项")
# 输入框和添加按钮
self.entry = tk.Entry(root, width=30)
self.entry.pack(pady=10)
self.add_btn = tk.Button(root, text="添加待办", command=self.add_todo)
self.add_btn.pack(pady=5)
# 待办列表(用Listbox显示)
self.todo_list = tk.Listbox(root, width=40, height=10)
self.todo_list.pack(pady=10)
# 删除按钮
self.del_btn = tk.Button(root, text="删除选中项", command=self.delete_todo)
self.del_btn.pack(pady=5)
def add_todo(self):
todo = self.entry.get().strip() # 获取输入内容并去空格
if todo:
self.todo_list.insert(tk.END, todo) # 添加到列表末尾
self.entry.delete(0, tk.END) # 清空输入框
else:
messagebox.showwarning("提示", "请输入待办事项!")
def delete_todo(self):
selected = self.todo_list.curselection() # 获取选中的索引
if selected:
self.todo_list.delete(selected[0]) # 删除选中项
if __name__ == "__main__":
root = tk.Tk()
app = TodoApp(root)
root.mainloop() # 启动主事件循环
3. 关键操作说明
- **
pack()**:最简单的布局,组件按添加顺序垂直/水平排列(默认垂直)。 - **
grid()**:网格布局,通过row(行)和column(列)定位(类似Excel表格)。 - 事件处理:按钮点击用
command参数绑定函数;输入框内容变化用trace监听。
二、Pygame:开发游戏应用的利器
Pygame 是 Python 的第三方游戏开发库(需安装:pip install pygame),适合开发2D小游戏(如跑酷、射击、休闲游戏等)。
1. Pygame 核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 初始化 | 启动Pygame模块(必须第一步) | pygame.init() |
| 游戏窗口 | 创建一个可交互的窗口(Surface对象) | screen = pygame.display.set_mode((800, 600)) |
| 游戏循环 | 程序的主循环,处理事件、更新状态、渲染画面(while running:) | running = True; while running: ... |
| 事件处理 | 监听键盘、鼠标等输入事件(pygame.event.get()) | for event in pygame.event.get(): if event.type == pygame.QUIT: running = False |
| 图形绘制 | 绘制矩形、圆形、图片等(pygame.draw.rect()、screen.blit()) | pygame.draw.circle(screen, (255,0,0), (400,300), 50)(画红圆) |
| 时钟控制 | 控制游戏帧率(Clock对象) | clock = pygame.time.Clock(); clock.tick(60)(限制60帧/秒) |
2. 快速上手:做一个「弹球游戏」
目标:窗口中一个球随机移动,碰到边缘反弹。
代码示例
import pygame
import random
# 初始化Pygame
pygame.init()
# 设置窗口(宽800,高600)
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("弹球游戏")
# 球的属性
ball_radius = 20
ball_x = random.randint(ball_radius, 800 - ball_radius) # 初始x坐标(避免卡边)
ball_y = random.randint(ball_radius, 600 - ball_radius) # 初始y坐标
ball_speed_x = random.choice([-4, -3, 3, 4]) # x方向速度(随机±3/±4)
ball_speed_y = random.choice([-4, -3, 3, 4]) # y方向速度
# 游戏主循环
running = True
clock = pygame.time.Clock() # 控制帧率
while running:
# 1. 处理事件(如关闭窗口)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 2. 更新球的位置
ball_x += ball_speed_x
ball_y += ball_speed_y
# 3. 碰撞检测(碰到窗口边缘反弹)
if ball_x <= ball_radius or ball_x >= 800 - ball_radius:
ball_speed_x = -ball_speed_x # 反转x速度
if ball_y <= ball_radius or ball_y >= 600 - ball_radius:
ball_speed_y = -ball_speed_y # 反转y速度
# 4. 渲染画面(先清屏,再画球,最后更新显示)
screen.fill((255, 255, 255)) # 白色背景
pygame.draw.circle(screen, (255, 0, 0), (ball_x, ball_y), ball_radius) # 红球
pygame.display.flip() # 更新整个窗口显示
# 5. 控制帧率(60帧/秒)
clock.tick(60)
# 退出Pygame
pygame.quit()
3. 关键操作说明
- 坐标系统:窗口左上角为
(0,0),x轴向右,y轴向下。 - 碰撞检测:通过判断球的位置是否超出窗口边界(
ball_x ± radius)来触发反弹。 - 帧率控制:
clock.tick(60)确保游戏每秒刷新60次,避免运行过快或过慢。
三、「大球吃小球」游戏(Pygame实现)
游戏规则:玩家控制一个大球(用鼠标或键盘移动),吃掉随机生成的小球(得分增加),碰到比自己大的球则游戏结束。
1. 游戏设计思路
- 角色:玩家球(可移动)、食物球(随机生成,被吃后消失)、敌人球(随机生成,可能比玩家大)。
- 核心逻辑:
- 玩家球通过鼠标/键盘移动。
- 食物球随机位置生成,玩家球碰到食物球则吃掉(得分+1,食物球重新生成)。
- 敌人球随机生成并移动,玩家球碰到比自己大的敌人球则游戏结束。
2. 完整代码示例
import pygame
import random
import sys
# 初始化Pygame
pygame.init()
# 窗口设置(宽800,高600)
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("大球吃小球")
# 颜色定义
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
# 玩家球属性
player_radius = 20
player_x = WIDTH // 2
player_y = HEIGHT // 2
player_speed = 5
player_score = 0
# 食物球属性(随机生成)
food_radius = 10
food_x = random.randint(food_radius, WIDTH - food_radius)
food_y = random.randint(food_radius, HEIGHT - food_radius)
# 敌人球列表(随机生成,数量3个)
enemies = []
for _ in range(3):
enemy_radius = random.randint(10, player_radius - 1) # 敌人比玩家小
enemy_x = random.randint(enemy_radius, WIDTH - enemy_radius)
enemy_y = random.randint(enemy_radius, HEIGHT - enemy_radius)
enemy_speed_x = random.choice([-3, -2, 2, 3])
enemy_speed_y = random.choice([-3, -2, 2, 3])
enemies.append([enemy_x, enemy_y, enemy_speed_x, enemy_speed_y])
# 游戏主循环
running = True
clock = pygame.time.Clock()
while running:
# 1. 处理事件(关闭窗口)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 2. 玩家球移动(鼠标控制)
mouse_x, mouse_y = pygame.mouse.get_pos()
player_x = mouse_x
player_y = mouse_y
# 限制玩家球不超出窗口
player_x = max(player_radius, min(player_x, WIDTH - player_radius))
player_y = max(player_radius, min(player_y, HEIGHT - player_radius))
# 3. 食物球被吃检测(玩家球与食物球碰撞)
distance_food = ((player_x - food_x) ** 2 + (player_y - food_y) ** 2) ** 0.5
if distance_food < player_radius + food_radius:
player_score += 1
food_x = random.randint(food_radius, WIDTH - food_radius)
food_y = random.randint(food_radius, HEIGHT - food_radius)
# 食物球变小(可选,增加难度)
# food_radius = max(5, food_radius - 1)
# 4. 敌人球移动与碰撞检测
for enemy in enemies:
enemy_x, enemy_y, enemy_speed_x, enemy_speed_y = enemy
# 敌人球移动
enemy_x += enemy_speed_x
enemy_y += enemy_speed_y
# 敌人球碰到窗口边缘反弹
if enemy_x <= enemy_radius or enemy_x >= WIDTH - enemy_radius:
enemy_speed_x = -enemy_speed_x
if enemy_y <= enemy_radius or enemy_y >= HEIGHT - enemy_radius:
enemy_speed_y = -enemy_speed_y
# 更新敌人球位置
enemy[0], enemy[1] = enemy_x, enemy_y
# 玩家球与敌人球碰撞检测
distance_enemy = ((player_x - enemy_x) ** 2 + (player_y - enemy_y) ** 2) ** 0.5
if distance_enemy < player_radius + enemy_radius:
# 如果敌人球比玩家大,游戏结束
if enemy_radius > player_radius:
font = pygame.font.Font(None, 74)
text = font.render("游戏结束!", True, RED)
screen.blit(text, (WIDTH//2 - 140, HEIGHT//2 - 50))
pygame.display.flip()
pygame.time.wait(2000) # 显示2秒后退出
running = False
# 否则吃掉敌人球(得分+1,敌人球重新生成)
else:
player_score += 1
enemy_radius = random.randint(10, player_radius - 1)
enemy_x = random.randint(enemy_radius, WIDTH - enemy_radius)
enemy_y = random.randint(enemy_radius, HEIGHT - enemy_radius)
enemy_speed_x = random.choice([-3, -2, 2, 3])
enemy_speed_y = random.choice([-3, -2, 2, 3])
enemy[2], enemy[3] = enemy_speed_x, enemy_speed_y
enemy[0], enemy[1] = enemy_x, enemy_y
# 5. 渲染画面
screen.fill(WHITE) # 清屏(白色背景)
# 画玩家球(蓝色)
pygame.draw.circle(screen, BLUE, (player_x, player_y), player_radius)
# 画食物球(绿色)
pygame.draw.circle(screen, GREEN, (food_x, food_y), food_radius)
# 画敌人球(红色)
for enemy in enemies:
pygame.draw.circle(screen, RED, (enemy[0], enemy[1]), enemy[2])
# 显示得分(白色字体)
font = pygame.font.Font(None, 36)
score_text = font.render(f"得分: {player_score}", True, WHITE)
screen.blit(score_text, (10, 10))
# 更新显示
pygame.display.flip()
# 控制帧率(60帧/秒)
clock.tick(60)
# 退出Pygame
pygame.quit()
sys.exit()
3. 代码关键说明
- 玩家控制:用
pygame.mouse.get_pos()获取鼠标位置,直接控制玩家球移动。 - 碰撞检测:通过计算两个球圆心距离与半径之和的关系(
distance < r1 + r2)判断是否碰撞。 - 敌人球逻辑:随机生成位置和速度,碰到边缘反弹,被吃后重新生成(可能变大)。
四、总结(初学者必记)
- Tkinter:适合快速开发桌面工具,核心是组件、布局和事件绑定。
- Pygame:适合开发2D游戏,核心是游戏循环、图形绘制和碰撞检测。
- 大球吃小球:通过碰撞检测、分数系统和游戏结束逻辑,理解游戏开发的基本流程。
动手提示:
- 尝试修改Tkinter待办事项工具的样式(如按钮颜色、字体)。
- 在Pygame弹球游戏中添加音效(用
pygame.mixer.Sound)。 - 在大球吃小球游戏中增加更多敌人类型(如移动更快的敌人)。
遇到问题多查文档(Tkinter文档、Pygame文档),多运行代码观察效果! 😊
Python 学习 笔记(第11天)--文件和异常
一、读文件:3 种常用方式 + 路径处理
文件操作是程序与外部数据交互的基础,读文件是最常用的功能之一。
1. 读取整个文件(小文件适用)
适用场景:文件内容较少(如配置文件、小文本)。
核心方法:read()、readline()、readlines()
| 方法 | 说明 | 示例 |
|---|---|---|
f.read() | 一次性读取全部内容为字符串(大文件慎用,可能内存溢出) | content = f.read() → 输出:`"你好,世界 |
| 这是第二行"` | ||
f.readline() | 每次读取一行(循环读取可处理大文件) | 第一次调用:`"你好,世界 |
";第二次调用:"这是第二行 | ||
| "` | ||
f.readlines() | 一次性读取所有行,返回列表(每行末尾带换行符) | `["你好,世界 |
| ", "这是第二行 | ||
| "]` |
代码示例:
# 读取整个文件(小文件)
with open("demo.txt", "r", encoding="utf-8") as f:
content = f.read() # 一次性读取全部内容
print(content)
# 逐行读取(大文件友好)
with open("big_file.log", "r", encoding="utf-8") as f:
for line in f: # 直接循环文件对象,逐行读取(内存友好)
print(line.strip()) # strip() 去掉行末换行符
2. 文件路径:绝对路径 vs 相对路径
- 绝对路径:从电脑根目录开始的完整路径(如
C:\Users\user\file.txt或/home/user/file.txt)。 - 相对路径:相对于当前运行脚本的路径(如脚本在
D:\project\,./data.txt表示D:\project\data.txt)。
注意:
- Windows 用反斜杠
\,Linux/macOS 用斜杠/,Python 中两种都支持,但推荐用/避免转义问题。 - 路径错误会报
FileNotFoundError,可用os.path.exists("路径")检查路径是否存在(需导入os模块)。
二、写文件:覆盖/追加 + 文本/二进制
写文件是将程序数据保存到外部的关键操作,需注意模式选择。
1. 模式说明(核心参数 mode)
| 模式 | 含义 | 示例 |
|---|---|---|
'w' | 覆盖写入(文件存在则清空内容,不存在则创建) | open("log.txt", "w", encoding="utf-8") |
'a' | 追加写入(在文件末尾添加内容,不覆盖原有内容) | open("log.txt", "a", encoding="utf-8") |
'wb' | 二进制覆盖写入(用于图片、视频等非文本文件) | open("image.jpg", "wb") |
'ab' | 二进制追加写入 | open("image.jpg", "ab") |
2. 文本 vs 二进制文件
- 文本文件:直接用字符串读写(如
.txt、.py),需指定encoding(推荐utf-8)。 - 二进制文件:用字节(
bytes)读写(如图像、音频),无需指定编码。
代码示例:
# 覆盖写入文本文件(清空原内容,写入新内容)
with open("diary.txt", "w", encoding="utf-8") as f:
f.write("2023-10-01 天气晴
")
f.write("今天学习了Python文件操作
")
# 追加写入文本文件(保留原内容,添加新内容)
with open("diary.txt", "a", encoding="utf-8") as f:
f.write("2023-10-02 天气雨
")
f.write("今天复习了异常处理
")
# 二进制写入(保存图片)
with open("logo.png", "rb") as src_f: # 读取二进制原图
img_data = src_f.read()
with open("new_logo.png", "wb") as dst_f: # 写入二进制到新文件
dst_f.write(img_data)
三、异常处理:让程序更健壮
程序运行中难免出错(如文件不存在、网络中断),异常处理能避免程序崩溃,并给出友好提示。
1. 异常机制的重要性
- 防崩溃:捕获错误并处理,避免程序直接终止。
- 调试友好:通过异常信息快速定位问题(如哪一行代码出错)。
- 用户友好:给用户明确的错误提示(如“文件不存在,请检查路径”)。
2. 核心代码块:try-except-else-finally
try:
# 可能出错的代码(如打开不存在的文件)
with open("no_such_file.txt", "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError as e: # 捕获特定异常(文件不存在)
print(f"错误:文件未找到!具体原因:{e}")
except Exception as e: # 捕获其他未知异常(兜底)
print(f"发生未知错误:{e}")
else:
# 只有 try 成功执行时,才执行 else 里的代码
print("文件读取成功,内容长度:", len(content))
finally:
# 无论是否出错,finally 都会执行(常用于清理资源)
print("操作结束,清理临时资源...")
3. 常见内置异常类型
| 异常类型 | 说明 | 示例场景 |
|---|---|---|
FileNotFoundError | 文件/目录不存在 | 打开 no_such_file.txt |
PermissionError | 无权限访问文件(如只读文件尝试写入) | 用 w 模式打开只读文件 |
ValueError | 数值转换错误(如字符串转整数失败) | int("abc") |
TypeError | 类型错误(如字符串和数字相加) | "5" + 10 |
4. 主动抛异常:raise
当需要自定义错误条件时,可用 raise 主动抛出异常。
示例:
age = -5
if age < 0:
raise ValueError("年龄不能为负数!") # 主动抛出异常
四、数据持久化:CSV 与 JSON
数据持久化是将内存数据保存到磁盘,下次运行程序时可重新加载。常用格式:CSV(表格)、JSON(结构化数据)。
1. CSV 文件(逗号分隔值)
特点:简单易读,适合存储表格数据(如学生成绩、员工信息)。
操作模块:csv(Python 内置)。
代码示例:
import csv
# 写入 CSV(覆盖模式)
students = [
["姓名", "年龄", "成绩"],
["张三", 18, 90],
["李四", 19, 85]
]
with open("students.csv", "w", newline="", encoding="utf-8") as f: # newline="" 避免空行
writer = csv.writer(f)
writer.writerows(students) # 写入多行
# 读取 CSV(逐行读取)
with open("students.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
print(row) # 输出:["姓名", "年龄", "成绩"], ["张三", 18, 90], ...
# 用字典读写(更直观,列名作为键)
with open("students.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f) # 自动将首行作为字典的键
for row in reader:
print(f"姓名:{row['姓名']}, 成绩:{row['成绩']}") # 输出:姓名:张三, 成绩:90
2. JSON 文件(JavaScript 对象表示法)
特点:结构灵活(支持字典、列表),跨语言通用(几乎所有编程语言都支持解析)。
操作模块:json(Python 内置)。
代码示例:
import json
# 字典转 JSON(序列化)
user_info = {
"name": "张三",
"age": 20,
"hobbies": ["编程", "读书"]
}
json_str = json.dumps(user_info, ensure_ascii=False) # ensure_ascii=False 显示中文
print(json_str) # 输出:{"name": "张三", "age": 20, "hobbies": ["编程", "读书"]}
# JSON 写入文件
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user_info, f, ensure_ascii=False) # 直接写入文件
# 读取 JSON 文件(反序列化)
with open("user.json", "r", encoding="utf-8") as f:
loaded_data = json.load(f)
print(loaded_data["hobbies"][0]) # 输出:编程
总结
读文件:小文件用 read(),大文件逐行跑;路径别写错,编码要选好。
写文件:覆盖用 w,追加用 a;文本加编码,二进制用 b。
异常处理:try 里放风险,except 捕错误;finally 必执行,清理资源别忘却。
数据持久化:CSV 表格简单,JSON 结构灵活;csv 和 json 模块,轻松搞定存读。
Python 学习 笔记(第12天)--字符串和正则表达式
- 字符串高级操作 - 转义字符 / 原始字符串 / 多行字符串 /
in和not in运算符 /is_xxx方法 /join和split方法 /strip相关方法 /pyperclip模块 / 不变字符串和可变字符串 /StringIO的使用 - 正则表达式入门 - 正则表达式的作用 / 元字符 / 转义 / 量词 / 分组 / 零宽断言 /贪婪匹配与惰性匹配懒惰 / 使用
re模块实现正则表达式操作(匹配、搜索、替换、捕获) - 使用正则表达式 -
re模块 /compile函数 /group和groups方法 /match方法 /search方法 /findall和finditer方法 /sub和subn方法 /split方法 - 应用案例 - 使用正则表达式验证输入的字符串
Python 学习 笔记(第13天)--进程和线程
- 进程和线程的概念 - 什么是进程 / 什么是线程 / 多线程的应用场景
- 使用进程 -
fork函数 /multiprocessing模块 / 进程池 / 进程间通信 - 使用线程 -
threading模块 /Thread类 /RLock类 /Condition类 / 线程池
Python 学习 笔记(第14天)--网咯编程入门和网络应用开发
- 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念
- 网络应用模式 - “客户端-服务器”模式 / “浏览器-服务器”模式
- 基于HTTP协议访问网络资源 - 网络API概述 / 访问URL /
requests三方库 / 解析JSON格式数据 - Python网络编程 - 套接字的概念 /
socket模块 /socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 - 电子邮件 - SMTP协议 / POP3协议 / IMAP协议 /
smtplib模块 /poplib模块 /imaplib模块 - 短信服务 - 调用短信服务网关
Python 学习 笔记(第15天)--图像和文档处理
- 用Pillow处理图片 - 图片读写 / 图片合成 / 几何变换 / 色彩转换 / 滤镜效果
- 读写Word文档 - 文本内容的处理 / 段落 / 页眉和页脚 / 样式的处理
- 读写Excel文件 -
xlrd/xlwt/openpyxl

被折叠的 条评论
为什么被折叠?



