3、Python基础速通(一):变量与数据类型、列表与字典、条件判断与循环、函数定义

各位同学,欢迎来到Python基础速通的第一讲。说实话,车载网络测试的脚本开发,不需要你把Python学到精通级别。但有几个核心概念,你必须得吃透。今天这一讲,就是帮你把地基打牢。

我见过不少新人,上来就抄网上的脚本,结果变量名乱起、数据类型搞混,跑起来全是坑。咱们做车载测试的,脚本跑在实车上,一个类型错误就可能导致CAN报文解析失败,甚至影响测试结论。所以,咱们稳扎稳打来。

3.1 变量与数据类型

变量,说白了就是给数据贴个标签。在Python里,你不需要像C语言那样提前声明类型。直接赋值就行。

# 这就是变量
ecu_name = "BCM"
can_id = 0x123
voltage = 12.5
is_awake = True

Python会自动推断类型。我个人习惯用下划线命名法,比如 ecu_namecan_id,这样在写长脚本时一眼就能看懂。

常用的数据类型,我列个表给你看:

类型 示例 说明
int 100, 0x1A 整数,CAN ID常用十六进制
float 12.5, 3.1415 浮点数,电压、电流值
str "BCM", '0x123' 字符串,DID名称、报文描述
bool True, False 布尔值,信号状态判断
bytes b'\x01\x02' 字节串,CAN报文原始数据
注意: 我曾经在解析DTC状态时,把十六进制字符串当成了整数直接运算,结果算出来的掩码全错了。记住,"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("找到了发动机转速信号")
我的经验: 在写自动化测试脚本时,我习惯用字典来存DTC的故障码和对应的描述。这样查起来特别快,比用if-else链优雅多了。

3.3 条件判断与循环

脚本的流程控制,全靠这两个。没有它们,你的脚本就是一条直线跑到底。

3.3.1 条件判断

Python用 ifelifelse 来做判断。注意缩进,这是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无响应,超时")
避坑指南: 我曾经写过一个while循环,忘记加 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) 读完就清。

好了,这一讲的内容就这些。变量、列表字典、条件循环、函数,这四个东西你练熟了,车载网络测试脚本的基本骨架就有了。下一讲,咱们聊聊文件操作和异常处理——这两个在实车测试中特别实用。