深圳融克迪特科技有限公司 Logo,金融科技,量化交易,软件开发

深圳融克迪特科技有限公司

RONG CREDIT TECHNOLOGY CO., LTD.

基础入门

【Python 系列 第7讲】异常处理:避开空值和除零

本讲用最小样本演示空字符串、类型转换失败和除零风险如何打断收益率脚本,并通过 try/except 与条件判断做基础防护,让初学者开始建立先清洗、再计算的处理习惯。

2026-04-26 智铨研究 阅读时长 7 分钟

目录

Python · 入门短课

  1. 第 1 讲【Python 系列 第1讲】环境检查:先打印一组收盘价
  2. 第 2 讲【Python 系列 第2讲】列表和字典:装下价格与日期
  3. 第 3 讲【Python 系列 第3讲】for循环:批量计算日收益率
  4. 第 4 讲【Python 系列 第4讲】函数封装:写一个收益率计算器
  5. 第 5 讲【Python 系列 第5讲】条件判断:筛出上涨交易日
  6. 第 6 讲【Python 系列 第6讲】CSV读写:保存再读回价格表
  7. 第 7 讲【Python 系列 第7讲】异常处理:避开空值和除零
  8. 第 8 讲【Python 系列 第8讲】生成一份行情摘要

一、为什么异常处理这一讲,不是补充知识,而是让入门脚本第一次具备“抗脏数据”能力

很多人在学 Python 量化入门时,前几讲会觉得一切都挺顺。价格列表干净、CSV 读写顺利、收益率函数也能输出结果,于是很容易形成一种错觉:只要公式和循环写对了,脚本自然就会一直跑下去。真实数据很快就会打破这种感觉。空字符串、缺失价格、上一日价格为 0,这些问题一点也不“高级”,却恰恰是最容易让入门脚本当场中断的常见事故。

这就是为什么第 7 讲必须单独讲异常处理。它不是一个可有可无的补丁,而是在帮你的脚本第一次建立基本的防守能力。也就是当坏样本出现时,程序不再只能直接崩掉,而是开始学会识别、跳过或提示。这种能力对量化小脚本非常重要,因为真实世界里的问题往往不是模型太难,而是输入太脏。只要这一层没有先守住,前面写得再整齐的循环和函数,也很容易在某个小脏值面前全部停住。

因此,第 7 讲真正要建立的,不是炫技式的异常语法,而是一种非常务实的程序意识:在真正开始计算前,先问问输入是不是值得直接算。

二、为什么空值和除零会被放在一起讲,因为它们都属于“最常见的中断点”

异常情况其实可以很多,但入门阶段没必要一上来就铺得太广。空值和除零之所以被放在这一讲一起讲,是因为它们恰好是最常见、最容易验证、也最容易让收益率脚本直接中断的两类问题。空值会在类型转换阶段就出事,除零则会在真正计算收益率时引发失败。它们出现的环节不同,但都属于“脚本还没来得及产出结果,就被迫停下来”的典型中断点。

把这两者放在一起讲,有一个很大的好处:你会更清楚地看到异常不是只有一种形态。有的异常来自输入压根不合法,比如空字符串根本不能转成浮点数;有的异常则来自输入虽然是数值,但在当前公式里不适合作为分母。只要你能把这两类问题分清,后面遇到别的异常时也更容易判断它到底属于哪一层。

所以第 7 讲并不是随机挑了两个问题,而是在刻意帮你建立一种分层视角:坏样本可能在进入计算前就该被拦下,也可能在计算阶段才被判定不适合继续用。

三、为什么先做类型转换清洗,再进入收益率循环,是一个非常值得固定下来的顺序

一旦数据可能带着空字符串或别的脏值,最不稳的做法就是一边循环算收益率,一边才临时发现某项根本转不成数值。更稳的顺序,是先把原始样本过一遍清洗:能转成浮点数的留住,不能转的先识别出来并处理掉,然后再把清洗后的序列交给收益率计算。这种两段式流程比把所有事情揉在一个循环里要清楚得多。

这个顺序之所以值得固定,不只是因为它能避免报错,更因为它在结构上把问题拆开了。第一段负责确认“输入值是不是可计算”,第二段负责真正执行收益率公式。只要这两段职责清楚,你后面无论增加日志、换别的清洗策略,还是进一步封装函数,都会自然很多。相反,如果从一开始就把清洗和计算揉在一起,代码很快就会变得难读,也更难定位问题到底发生在哪一层。

因此,第 7 讲里“先清洗再计算”的顺序,不该被理解成临时补锅,而应该被当成一个很值得延续的数据处理习惯。

四、为什么try/except和条件判断在这里各管一段,不应该混为一谈

很多初学者一接触异常处理,就容易把所有问题都往 try/except 里塞,好像只要能被 except 接住,脚本就算稳了。实际上,第 7 讲非常适合帮你看清:try/except 和普通条件判断虽然都能阻止程序崩掉,但它们解决的问题并不一样。try/except 更适合处理“程序一旦尝试执行某个动作就可能报错”的场景,比如把空字符串转成浮点数;而 if prev_price == 0 这种条件判断,则是在逻辑层面提前识别“这个值虽然合法,但不适合进入当前公式”。

把这两者分清非常重要。因为它会帮助你以后更自然地判断:这个问题是应该用异常机制去兜,还是应该用显式规则提前挡住。对当前收益率脚本来说,这种区分尤其清楚。空值属于类型转换失败,除零风险属于业务规则下不能继续算。两者若混成一类看,代码会显得很重,也更难解释。

所以第 7 讲其实不只是教你两种写法,而是在顺手建立一种更成熟的问题分类方式。只要这层分类建立起来,后面你写稳健代码时会省很多力气。

五、为什么“跳过坏样本继续处理”比“一出错就整体停下”更适合当前阶段

在某些严肃生产场景里,遇到坏数据完全可以选择立刻报错停下,让人来检查。但对当前这个入门系列来说,更适合作为第一步的策略,是在发现明显坏样本时先跳过,并保留简单提示,让脚本继续处理后面的可用数据。这样做有两个好处。第一,你能非常直观地看到保护逻辑是否真的生效,因为程序没有在中途崩掉。第二,它会让你第一次建立“单条坏样本不一定应该拖死整批处理”的感觉。

这种感觉对量化练习非常重要。因为现实里的数据问题经常不是整批都错,而只是个别记录不干净。若每次都只会一错就停,你会很难建立对整批数据处理的掌控感。当前用“跳过并提示”的方式,既保留了异常的可见性,又不会让流程完全断掉,是非常适合入门阶段的一种折中方式。

所以第 7 讲不是在教你忽略错误,而是在教你:面对最常见的小脏值,脚本应该先学会不被轻易击穿。

六、为什么这一讲真正保护的,不只是脚本能不能跑完,而是结果有没有基本可信度

很多人一提异常处理,首先想到的是“防止程序崩”。这当然是其中一层意义,但对数据分析来说,更深一层其实是保护结果可信度。因为如果坏值直接混进收益率计算,你得到的不只是一个报错风险,还可能是一串看起来有结果、其实含义已经失真的输出。比如字符串没转好、分母为 0 却被粗暴处理,最终都会让结果解释变得不可靠。

所以第 7 讲的价值,不应只理解为“让程序继续运行”,而应理解为“确保进入计算层的样本至少满足最基本条件”。这是一种非常重要的数据防线意识。只要你在输入和计算之间先加上这道门,后面的结果即使还不完美,至少已经比完全裸奔式处理稳得多。

对量化入门来说,这种意识比学更多花哨功能更重要。因为真实研究里最让人头疼的,往往不是不会写公式,而是结果看着有,但你越来越不敢信。第 7 讲正是在帮你提前防止这种情况。

七、为什么这一讲会让你第一次真正感受到“防守式编程”是什么

前几讲的代码更偏进攻,也就是假设输入大体正常,然后顺着逻辑推进。第 7 讲则第一次把另一种思路带进来:在计算之前,先预想最常见的失败点,然后主动加防守。这种写法有时被称为防守式编程。对入门者来说,这个概念听起来也许有点大,但在当前这节课里其实非常具体。你只是提前想了一步:如果有空字符串怎么办?如果分母等于 0 怎么办?

这种“先想失败点再开算”的习惯非常宝贵。因为它会让你逐渐摆脱一种幼稚状态:总以为只要理想样本能跑通,代码就算完成。真正更稳的脚本,往往是在理想路径之外,也给常见问题留了处理空间。第 7 讲正是第一次让你真实地体验这种差异。

从长期看,这种习惯会越来越有价值。哪怕以后你改用 pandas 或别的框架,防守式编程的思路依然会跟着你走。当前先在最小收益率脚本里练出来,非常合适。

八、这一讲为最后的行情摘要生成准备了什么

只要空值和除零风险已经被挡在计算层之前,下一讲的摘要生成就会稳很多。因为摘要要基于价格、收益率和筛选结果做总结,如果底层结果还随时可能被坏样本打断,那摘要本身也很难站住。换句话说,第 7 讲相当于是在最后一讲之前,先把整条小工作流的稳健性补齐一层。

这也解释了为什么系列安排把异常处理放在倒数第二讲。前面先学会算、会筛、会读写;到了这里,再把整条链路最常见的脏值风险挡住;最后再去组织摘要,整个流程就会更像一条真正可用的小脚本,而不是只能在理想样本上跑的演示代码。

所以,第 7 讲虽然看起来像是在处理“问题情况”,其实是在给最后的结果组织做地基。只要这里先稳住,收尾那一讲会自然很多。

九、为什么这一讲做完后,最好已经形成“防守不是补丁,而是流程要求”的认识

很多人第一次写异常处理时,容易把它理解成哪里报错就补哪里,好像只是给程序贴几个创可贴。第 7 讲更值得建立的认识是,防守并不是零碎补丁,而是工作流本身的要求。因为只要样本会来自文件、来自外部输入,就几乎一定会遇到空值、坏值或除零风险。只要这层现实感已经建立,你就会更自然地把防守动作提前到计算之前,而不是总等到报错以后再想办法。

这种认识非常关键。因为它会直接改变你写脚本的姿态。你不再只是追求“这次能跑”,而会开始追求“下次换一批样本也尽量稳”。

十、这一讲也在帮你形成“清洗层和计算层要分开”的边界意识

异常处理还有一个很实用的价值,就是在训练你把清洗层和计算层分开。遇到空值时,先决定要不要跳过、替换或拦下;遇到除零风险时,先在规则层做显式判断;等这些边界处理清楚以后,再把干净样本送进收益率计算。只要这种分层意识开始稳定,后面脚本就会明显更清楚,不会所有判断都缠在一团。

这层边界意识在后面会不断复用。因为只要数据世界不是理想的,你就总要面对“先挡住问题,再继续计算”这类判断。

十一、这一讲结束时,最好已经具备怎样的完成感

如果这一讲已经真正落地,你通常会有一种很明确的完成感:你不再把报错看成偶然事故,而开始把它理解成输入层和计算层之间需要被认真处理的边界问题。你知道哪些问题该在清洗阶段拦下,哪些问题该在计算时显式判断,也知道为什么这些防守动作不能等到程序炸掉以后才想起来。只要这种边界感已经形成,说明异常处理已经从“补救动作”变成了工作流的一部分。

这种完成感非常有价值,因为它会直接让你后面的摘要输出更稳。只有底层已经不会轻易被坏样本打穿,最后的结果组织才真正可靠。

十二、总结

这一讲的重点,不只是让程序不要报错,而是让你的入门收益率脚本第一次具备基本的抗脏数据能力。你需要理解空值和除零虽然都可能中断脚本,但属于不同层次的问题,也要学会先清洗再计算、该用 try/except 的地方用异常保护、该用条件判断的地方用显式规则提前挡住。只要这些层已经建立起来,这一讲就真正完成了它的作用。

十三、系列衔接

本讲是《Python量化入门短课》的第 7 讲,当前主题是《异常处理:避开空值和除零》。上一讲已经把价格样本写入 CSV 并成功读回,这一讲则开始让整条小流程具备对常见坏值的基本防守能力。下一讲会在此基础上生成一份更完整的行情摘要,把前面几讲得到的结果真正组织成一份可读输出。

十四、风险揭示与免责声明

风险揭示与免责声明

本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。

本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。

市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。

读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。