2、Python基础速通(上)
各位同学好,我是老张。在光学测试这行摸爬滚打十几年,从最早用LabVIEW写采集程序,到后来用C#搭上位机,再到如今全面转向Python——说实话,Python是我用过最顺手的工具。今天咱们就来聊聊Python的基础知识,这部分内容我会分成上下两篇来讲。
你可能会问:做镜头测试,为啥要学Python?我举个例子。去年有个项目,需要批量处理5000张MTF测试图。如果用Excel手动算,三天都搞不完。我用Python写了个脚本,半小时搞定。这就是Python的魅力——简单、高效、生态好。
本章核心知识点:变量与数据类型、字符串操作、列表与字典、条件判断与循环、函数定义与调用。这些是Python的"内功心法",后面所有自动化测试脚本都离不开它们。
2.1 变量与数据类型
Python的变量声明,跟C语言完全不一样。你不用写 int a = 10,直接写 a = 10 就行。Python会自动推断类型。我第一次用Python时觉得这太随意了,后来发现——嗯,真香。
常用的数据类型就这几种:
| 类型 | 写法示例 | 说明 |
|---|---|---|
| 整数 | count = 100 | 镜头数量、像素坐标 |
| 浮点数 | mtf_value = 0.85 | MTF值、焦距、光圈 |
| 字符串 | lens_name = "广角镜头" | 镜头型号、测试报告 |
| 布尔值 | is_pass = True | 测试结果通过/不通过 |
| None | result = None | 表示空值,还没测到数据 |
我的小习惯:在写测试脚本时,我习惯用type()函数检查变量类型。特别是从文件读取数据时,经常发现读进来的是字符串而不是数字——这种坑我踩过不下十次。
# 实际项目中的例子:读取镜头参数
focal_length = "50" # 从配置文件读进来的是字符串
print(type(focal_length)) # <class 'str'>
# 必须转换才能做数学运算
focal_length = float(focal_length)
print(focal_length * 2) # 100.0
2.2 字符串操作
字符串操作在测试脚本里太常用了。生成报告、拼接文件路径、格式化输出——哪哪都离不开它。
先说字符串拼接。我见过很多新手用 + 号拼字符串,其实有更好的办法:
# 不推荐的方式
report = "镜头型号:" + lens_name + ",MTF值:" + str(mtf)
# 推荐的方式——f-string(Python 3.6+)
report = f"镜头型号:{lens_name},MTF值:{mtf:.2f}"
print(report)
# 输出:镜头型号:广角镜头,MTF值:0.85
字符串切片也很实用。比如从文件路径里提取文件名:
path = "D:/test_data/2024/MTF_广角镜头_001.csv"
# 提取文件名
filename = path.split("/")[-1]
print(filename) # MTF_广角镜头_001.csv
# 提取型号部分
model = filename.split("_")[1]
print(model) # 广角镜头
我曾经踩过的坑:用split()切分中文字符串时,如果字符串里有特殊符号(比如全角逗号、空格),很容易切错。建议先用replace()统一替换成半角符号再切分。
2.3 列表与字典
列表和字典是Python里最常用的两种数据结构。说白了,列表就是有序的"购物清单",字典就是带标签的"储物柜"。
先看列表——我经常用它来存一组测试数据:
# 存储多个镜头的MTF值
mtf_values = [0.82, 0.85, 0.79, 0.88, 0.81]
# 添加新数据
mtf_values.append(0.86)
# 遍历并计算平均值
total = 0
for val in mtf_values:
total += val
avg = total / len(mtf_values)
print(f"平均MTF值:{avg:.3f}")
字典就更灵活了。每个镜头有多个属性,用字典存最合适:
# 一个镜头的完整测试数据
lens_data = {
"型号": "GW-50mm",
"焦距": 50.0,
"MTF_中心": 0.85,
"MTF_边缘": 0.72,
"畸变": -0.3,
"测试日期": "2024-01-15"
}
# 读取某个值
print(lens_data["MTF_中心"]) # 0.85
# 更新数据
lens_data["MTF_中心"] = 0.87
实际项目经验:我在做镜头批量测试时,会把所有镜头的测试结果放在一个列表里,列表的每个元素都是一个字典。这样既方便遍历,又能快速查找某个镜头的所有数据。
# 批量测试数据管理
all_lenses = [
{"型号": "A001", "MTF": 0.85, "结果": "通过"},
{"型号": "A002", "MTF": 0.72, "结果": "不通过"},
{"型号": "A003", "MTF": 0.88, "结果": "通过"},
]
# 找出所有不通过的镜头
failed = [lens for lens in all_lenses if lens["结果"] == "不通过"]
print(failed) # [{'型号': 'A002', 'MTF': 0.72, '结果': '不通过'}]
2.4 条件判断与循环
条件判断和循环,是让程序"活起来"的关键。没有它们,代码就是一条道走到黑。
条件判断最常用的场景就是测试结果判定:
mtf_value = 0.78
threshold = 0.80
if mtf_value >= threshold:
print("测试通过")
elif mtf_value >= threshold * 0.9:
print("边缘合格,需复测")
else:
print("测试不通过")
循环嘛,说白了就是"重复干活"。我写测试脚本时,最常用的就是 for 循环:
# 批量处理100个镜头的测试数据
for i in range(1, 101):
filename = f"lens_{i:03d}.csv"
# 这里调用处理函数
print(f"正在处理第{i}个镜头:{filename}")
我的建议:range()函数里的步长参数很好用。比如每隔5个镜头抽检一次,可以写 range(0, 100, 5)。这种小技巧能省不少事。
2.5 函数定义与调用
函数就是把一段逻辑封装起来,给它起个名字,以后想用就调用这个名字。我写测试脚本时,会把每个测试项都写成独立的函数。
def calculate_mtf(image_path, frequency):
"""
计算指定频率下的MTF值
参数:
image_path: 图像文件路径
frequency: 空间频率(lp/mm)
返回:
mtf值(浮点数)
"""
# 这里是MTF计算逻辑(简化版)
# 实际项目中会调用OpenCV等库
mtf_result = 0.85 # 假设计算结果是0.85
return mtf_result
# 调用函数
result = calculate_mtf("test_image.bmp", 30)
print(f"30 lp/mm下的MTF值:{result}")
函数参数还有一些高级用法,我挑两个最常用的说说:
# 默认参数——省得每次都要传
def test_lens(model, threshold=0.80):
print(f"测试镜头:{model},阈值:{threshold}")
# 测试逻辑...
test_lens("GW-50mm") # 使用默认阈值0.80
test_lens("GW-50mm", 0.85) # 自定义阈值
# 返回值可以是多个
def analyze_image(path):
mtf_center = 0.85
mtf_edge = 0.72
distortion = -0.3
return mtf_center, mtf_edge, distortion
center, edge, dist = analyze_image("test.bmp")
print(f"中心MTF:{center},边缘MTF:{edge}")
我曾经犯过的错:函数的默认参数如果是一个可变对象(比如列表、字典),多次调用会共享同一个对象。比如 def test(data=[]),第二次调用时 data 里还留着第一次的数据。正确的做法是用 None 做默认值,函数内部再创建新列表。
好了,Python基础速通的上半部分就讲到这里。这些内容看起来简单,但都是后面写自动化测试脚本的基石。我建议你打开Python环境,把上面的代码都敲一遍。光看不练,等于白看。