3、Python基础速通(一):变量与数据类型、列表与字典、条件判断与循环、函数定义
各位同学,欢迎来到Python基础速通的第一讲。说实话,车载网络测试的脚本开发,不需要你把Python学到精通级别。但有几个核心概念,你必须得吃透。今天这一讲,就是帮你把地基打牢。
我见过不少新人,上来就抄网上的脚本,结果变量名乱起、数据类型搞混,跑起来全是坑。咱们做车载测试的,脚本跑在实车上,一个类型错误就可能导致CAN报文解析失败,甚至影响测试结论。所以,咱们稳扎稳打来。
3.1 变量与数据类型
变量,说白了就是给数据贴个标签。在Python里,你不需要像C语言那样提前声明类型。直接赋值就行。
# 这就是变量
ecu_name = "BCM"
can_id = 0x123
voltage = 12.5
is_awake = True
Python会自动推断类型。我个人习惯用下划线命名法,比如 ecu_name、can_id,这样在写长脚本时一眼就能看懂。
常用的数据类型,我列个表给你看:
| 类型 | 示例 | 说明 |
|---|---|---|
| int | 100, 0x1A | 整数,CAN ID常用十六进制 |
| float | 12.5, 3.1415 | 浮点数,电压、电流值 |
| str | "BCM", '0x123' | 字符串,DID名称、报文描述 |
| bool | True, False | 布尔值,信号状态判断 |
| bytes | b'\x01\x02' | 字节串,CAN报文原始数据 |
"0x12" 是字符串,0x12 才是整数。
3.2 列表与字典
这两个是脚本开发里最常用的数据结构。列表像有序的抽屉柜,字典像带标签的储物箱。
3.2.1 列表
列表用方括号 [] 表示,可以放任何类型的数据。我在项目中常用它来存一组CAN ID或者一组测试用例。
# 定义一个CAN ID列表
can_ids = [0x100, 0x200, 0x300]
# 添加元素
can_ids.append(0x400)
# 访问元素(索引从0开始)
first_id = can_ids[0] # 结果是0x100
# 遍历列表
for id in can_ids:
print(f"当前CAN ID: {hex(id)}")
你想想看,如果你要发送一组诊断请求,用列表存起来,循环发送,多方便。
3.2.2 字典
字典用花括号 {} 表示,每个元素是 键:值 对。我特别喜欢用字典来存信号映射关系。
# 定义一个信号字典
signal_map = {
"EngineSpeed": 0x100,
"VehicleSpeed": 0x200,
"BrakeStatus": 0x300
}
# 通过键取值
engine_id = signal_map["EngineSpeed"]
# 添加新信号
signal_map["SteeringAngle"] = 0x400
# 判断键是否存在
if "EngineSpeed" in signal_map:
print("找到了发动机转速信号")
3.3 条件判断与循环
脚本的流程控制,全靠这两个。没有它们,你的脚本就是一条直线跑到底。
3.3.1 条件判断
Python用 if、elif、else 来做判断。注意缩进,这是Python的命根子。
voltage = 12.5
if voltage < 9.0:
print("电压过低,ECU可能复位")
elif voltage > 16.0:
print("电压过高,有损坏风险")
else:
print("电压正常,继续测试")
嗯,这里要注意:Python没有switch-case语句。如果你有多个条件要判断,用 if-elif-else 链,或者用字典映射替代。
3.3.2 循环
常用的就两种:for 循环和 while 循环。
for 循环适合遍历已知集合:
# 遍历CAN ID列表
test_ids = [0x100, 0x200, 0x300]
for id in test_ids:
send_can_message(id, data)
print(f"已发送ID: {hex(id)}")
while 循环适合条件控制:
# 等待ECU响应,超时退出
timeout = 5
start_time = time.time()
response_received = False
while time.time() - start_time < timeout:
if check_response():
response_received = True
break
time.sleep(0.1)
if response_received:
print("ECU响应正常")
else:
print("ECU无响应,超时")
break 条件,结果脚本在实车上无限循环,把CAN总线刷爆了。记住,while循环一定要有退出机制。
3.4 函数定义
函数,就是把一段重复用的代码打包起来。我建议你养成习惯:只要一段代码出现两次以上,就把它写成函数。
def send_diagnostic_request(ecu_id, service_id, data):
"""
发送诊断请求
:param ecu_id: 目标ECU的CAN ID
:param service_id: 诊断服务ID
:param data: 请求数据
:return: 响应数据
"""
request_id = ecu_id + 0x8 # 物理请求ID偏移
send_can_message(request_id, [service_id] + data)
response = wait_for_response()
return response
函数的好处很明显:
- 复用性:写一次,到处调用
- 可读性:函数名就是注释
- 可维护性:改一处,全脚本生效
我个人习惯给每个函数写docstring(就是函数体里的三引号注释)。这样过两个月回头看,自己写的代码还能看懂。
def read_dtc(ecu_id, clear=False):,这样调用时 read_dtc(0x100) 只读,read_dtc(0x100, True) 读完就清。
好了,这一讲的内容就这些。变量、列表字典、条件循环、函数,这四个东西你练熟了,车载网络测试脚本的基本骨架就有了。下一讲,咱们聊聊文件操作和异常处理——这两个在实车测试中特别实用。