3、Python基础速通(二):条件判断与循环、函数定义、文件读写操作、异常处理
好,咱们接着聊。上一节我们把Python的基本数据类型和容器过了一遍,算是把工具箱里的零件认全了。这一节,咱们要学的是怎么让这些零件动起来——说白了,就是让代码有脑子、有体力、还能自己处理烂摊子。
我个人习惯把这一章叫做「代码的三板斧」:判断、循环、函数。再加上文件读写和异常处理,基本上日常的数据处理工作,你就能独立上手了。我在储能项目里,80%的脚本都离不开这些基础结构。
3.1 条件判断:让代码有脑子
条件判断,说白了就是让代码学会「看情况办事」。你想想看,储能系统里判断电池温度是否过高、SOC是否越界,哪样离得开条件判断?
# 最基本的if结构
soc = 85 # 电池荷电状态,单位%
if soc > 80:
print("SOC过高,建议停止充电")
elif soc > 60:
print("SOC正常,继续充电")
else:
print("SOC偏低,建议充电")
这里有个细节我想强调一下——Python用缩进来表示代码块,而不是花括号。我刚开始用Python时,经常因为缩进不对导致逻辑错误。嗯,这里要注意:同一层级的代码缩进必须一致,一般用4个空格。
3.2 循环:让代码有体力
循环就是让代码反复干同一件事。处理储能数据时,经常要遍历几千几万条记录,手动操作不现实,循环就是干这个的。
3.2.1 for循环——最常用
# 遍历一个电池组的电压数据
voltages = [3.2, 3.5, 3.8, 4.1, 3.9]
for i, v in enumerate(voltages):
print(f"第{i+1}节电池电压: {v}V")
if v > 4.0:
print(" ⚠️ 电压偏高,请关注")
enumerate这个函数我特别喜欢。它同时返回索引和值,省得你手动维护一个计数器。我在处理储能BMS数据时,经常用它来定位异常电芯的位置。
3.2.2 while循环——条件驱动
# 模拟电池充电过程
soc = 20
while soc < 100:
soc += 5
print(f"当前SOC: {soc}%")
if soc >= 80:
print("进入涓流充电模式")
break # 提前退出循环
3.3 函数定义:把代码打包成工具
函数就是把一段逻辑封装起来,给它起个名字,以后随时调用。说白了,就是造工具。
def calculate_energy(voltage, current, time_hours):
"""
计算电池储能电量
参数:
voltage: 电压(V)
current: 电流(A)
time_hours: 时间(h)
返回:
能量(kWh)
"""
energy = voltage * current * time_hours / 1000
return energy
# 调用函数
result = calculate_energy(48, 100, 2)
print(f"储能电量: {result:.2f} kWh")
我个人习惯在写函数时,一定会加docstring(就是那个三引号注释)。为什么?因为三个月后你回头看自己的代码,如果没有注释,你根本想不起来这个函数是干嘛的。我在项目里吃过这个亏,现在养成了习惯。
- 一个函数只做一件事——单一职责
- 函数名要能看出功能——见名知意
- 参数不要太多——超过3个考虑用字典
- 尽量有返回值——方便链式调用
3.4 文件读写操作:和硬盘打交道
储能数据分析,数据从哪来?大部分是从文件来的。CSV、TXT、JSON,都是家常便饭。
3.4.1 读取文件
# 读取储能系统的日志文件
with open('bms_log.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content[:200]) # 只打印前200个字符
with语句是Python的上下文管理器,它会自动帮你关闭文件。我见过很多新手写代码,打开文件后忘了关,导致文件句柄泄漏。用with就永远不会出这个问题。
3.4.2 写入文件
# 保存处理后的数据
processed_data = [
"2024-01-15, 3.52, 25.3",
"2024-01-15, 3.48, 25.1",
"2024-01-15, 3.55, 25.6"
]
with open('output.csv', 'w', encoding='utf-8') as f:
f.write("时间,电压,温度\n")
for line in processed_data:
f.write(line + '\n')
print("数据已保存到 output.csv")
| 模式 | 说明 | 我常用的场景 |
|---|---|---|
| 'r' | 只读 | 读取历史数据 |
| 'w' | 写入(覆盖) | 保存处理结果 |
| 'a' | 追加 | 实时记录日志 |
| 'r+' | 读写 | 修改配置文件 |
3.5 异常处理:给代码穿上防弹衣
程序跑着跑着出错了怎么办?直接崩溃?那肯定不行。异常处理就是给代码加一层保护。
try:
# 尝试读取一个可能不存在的文件
with open('sensor_data.csv', 'r') as f:
data = f.read()
print("数据读取成功")
except FileNotFoundError:
print("文件不存在,请检查路径")
# 这里可以创建默认文件或使用备用数据
except PermissionError:
print("没有权限读取该文件")
except Exception as e:
print(f"发生了未知错误: {e}")
finally:
print("无论是否出错,这行都会执行")
为什么会需要finally?我举个例子:你在处理储能数据时,打开了一个数据库连接,不管处理成功还是失败,这个连接都得关闭。finally就是干这个的。
3.6 实战:储能数据清洗小脚本
把今天学的知识串起来,写一个实际能用的脚本。假设我们有一个电池温度记录文件,需要清洗掉异常值。
def clean_temperature_data(input_file, output_file, min_temp=10, max_temp=45):
"""
清洗电池温度数据
剔除超出合理范围(10°C ~ 45°C)的异常值
"""
cleaned_records = []
error_count = 0
try:
with open(input_file, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
try:
temp = float(line.strip())
if min_temp <= temp <= max_temp:
cleaned_records.append(temp)
else:
error_count += 1
print(f"第{line_num}行数据异常: {temp}°C,已剔除")
except ValueError:
error_count += 1
print(f"第{line_num}行数据格式错误: {line.strip()}")
# 保存清洗后的数据
with open(output_file, 'w', encoding='utf-8') as f:
for temp in cleaned_records:
f.write(f"{temp}\n")
print(f"清洗完成!有效数据: {len(cleaned_records)}条,异常数据: {error_count}条")
except FileNotFoundError:
print(f"错误:找不到文件 {input_file}")
except Exception as e:
print(f"处理过程中发生错误: {e}")
# 调用函数
clean_temperature_data('battery_temp.txt', 'battery_temp_clean.txt')
这个脚本里,我把条件判断、循环、函数、文件读写、异常处理全用上了。你想想看,如果不用这些结构,纯手工处理几百兆的日志文件,那得干到猴年马月去?
- 条件判断让代码能「看情况办事」——if/elif/else
- 循环让代码能「反复干活」——for/while
- 函数把逻辑「打包成工具」——def/return
- 文件读写让数据「持久化」——open/with
- 异常处理让程序「不崩溃」——try/except
好了,这一节的内容就到这。这些基础结构看着简单,但真正用好需要大量练习。我建议你找个真实的储能数据文件,试着写个清洗脚本跑一跑。遇到问题很正常,调试本身就是学习的过程。