ExpRe[5] python[2] raise语句,条件断点
文章目录
- 从一道动规看`raise`的常见用法
- 粗略编写算法
- 出错
- 用`raise`传递信息
- `raise`的用法总结
- 条件断点
- 总结和问答练习
时效性
本篇撰写时间为2021.11.14,由于计算机技术日新月异,博客中所有内容都有时效和版本限制,具体做法不一定总行得通,链接可能改动失效,各种软件的用法可能有修改。但是其中透露的思想往往是值得学习的。
Windows 10家庭中文版,版本20H2,操作系统内部版本19042.1288
本篇前置:
- ExpRe[4] python[1] 单元测试,算法题对拍
https://www.cnblogs.com/minor-second/p/15549364.html - 大致知道python3中的异常,
try
机制
从一道动规看raise
的常见用法
我们继续做算法设计与分析作业
考虑一个所有元素为正的 n ∗ n n*n n∗n二维数组(邻接矩阵),已知其中有且仅有一条有向回路使得该回路上各权值乘积大于1,试找出该回路。(特别注意可以自己到自己连边,且这样的边也有可能权重大于1)
其实括号提示是我自己加的。有点坑。
粗略编写算法
我们粗略编写如下类似于Floyd算法的程序
def find_loop(n, mat):max_mat = []for i in range(n):max_mat.append(mat[i].copy())for j in range(n):max_mat[i][j] = [max_mat[i][j], -1]loop_start = 0try:for k in range(n):for i in range(n):for j in range(n):if max_mat[i][k][0] * max_mat[k][j][0] > max_mat[i][j][0]:max_mat[i][j][0] = max_mat[i][k][0] * max_mat[k][j][0]max_mat[i][j][1] = kif i==j and max_mat[i][j][0] > 1:loop_start = iraise StopIterationexcept StopIteration:seq = [loop_start, loop_start]def insert(i,max_mat,seq):s, e = seq[i], seq[i+1]if max_mat[s][e][1] == -1:return seqseq = seq[:i+1] + [max_mat[s][e][1]] + seq[i+1:]seq = insert(i+1,max_mat,seq)seq = insert(i,max_mat,seq)return seqreturn insert(0,max_mat,seq)
- 首先深度拷贝输入
max_mat
防止改变输入对象(以便于测试)。并把原先矩阵中单独的数改成两个元素的表,表的第0个分量为权重(或多个权重乘积),第1个分量为“插入的点”。 - 使用类似Floyd算法的三重循环结构,最外层是依次考察“插入这个点是否变好”。先考察“ i → j i\to j i→j改成 i → 0 → j i\to 0\to j i→0→j是否变好”等 n 2 n^2 n2个命题,再考察“ i → j i\to j i→j改成 i → 1 → j i\to 1\to j i→1→j是否变好”等 n 2 n^2 n2个命题。考察完至多全部 k k k值共 n 3 n^3 n3个命题后就找到了回路。
其中max_mat[i][j][1] = k
语句就是存储插入的点,方便最后回溯得到路径。 - 为了得到路径,我们先得到一个路径上的点
loop_start
,然后递归地利用矩阵中记录的信息向其中插入中间节点。
insert
使用了递归,因此效率不会很高(当然都用python写算法题了也不在乎卡常了是吧)。
insert
函数有个细节是先插入i+1
处,再插入i
处,否则显然导致错误结果。
出错
我们编写一个单元测试看看该算法对不对。
文件树
在test2.py
中,输入代码
import unittest
import random
from problem2 import find_loop
class Test(unittest.TestCase):def test_auto(self):for _ in range(100):mat = list(list(random.random() * 0.8 for i in range(10)) for i in range(10))l = [i for i in range(10)]random.shuffle(l)n = random.randrange(1, 11)l = l[:n]pair_list = list((l[i-1], l[i]) for i in range(len(l)))for pair in pair_list:MAGIC = 0.9999mat[pair[0]][pair[1]] = MAGIClast_pair = pair_list[-1]mat[last_pair[0]][last_pair[1]] *= MAGIC**(-len(l)-1)seq = find_loop(10, mat)self.assertIn(l[0], seq)seq = seq[:-1] * 2for i in range(len(seq)):if seq[i] == l[0]:self.assertEqual(seq[i:i+len(l)],l)breakif __name__ == '__main__':unittest.main()
- 其思路是先生成元素都在 0 0 0至 0.8 0.8 0.8的10阶方阵,然后随机生成一个不重复的整数序列
l
(使用了shuffle
打乱)。 - 接着,例如对于序列
[1, 2, 3]
,生成二元组序列[(3,1), (1,2), (2,3)]
(特别注意负数下标使用),并人工改变这些序列对应的邻接矩阵中的权值,造出一条权重乘积大于1的回路。 - 调用算法得到的
seq
未必和l
相同。比如seq = [1,2,3,1]
,l = [3,1,2]
. 但我们只需把seq
去掉末尾元再重复2遍,其中就一定包含l
为“子串”了。
结果是有时能通过测试有时不能。试图改变循环次数100
为更大或更小的数值,发现有一个概率量级为 1 0 − 2 ∼ 1 0 − 1 10^{-2} \sim 10^{-1} 10−2∼10−1的错误。(回忆 ( 1 − 1 / n ) n ≈ 1 / e (1-1/n)^n\approx 1/e (1−1/n)n≈1/e)
报错RecursionError: maximum recursion depth exceeded in comparison
.
用raise
传递信息
我们用try
包裹出错的seq = find_loop(10, mat)
语句
try:seq = find_loop(10, mat)except RecursionError:raise RecursionError(seq, l, mat)
多次运行,发现输出的共同特点是l == [0]
. 这就方便找到错误了:当0到0路径权重大于1时,我们在0到0中间插入了点0,从而导致无限循环。(有趣的是,l == [1]
不会发生此错误。因为此时在外层循环到k==1
之前就已经能发现1到1的权重大于1了)
raise
的用法总结
- 用法之一:可以看到我们使用
try
包裹代码段,并用raise
手动引发异常,用except
捕捉直接跳出多重循环。 - 用法之二:在异常后加括号,其中添加任意多个参数,从而传递信息。
条件断点
对于新手(其实就是我),即使知道错误都出现在l == [0]
,也未必能马上看出错误。此时可能需要打条件断点方便调试。
- 错误做法:
if 条件:pass
在pass
处加断点可能无法起作用。因为pass
语句作为占位符,可能不对应任何实际编译出的代码,直接被“忽略”。
- 一种比较丑陋的做法是把
pass
改成...
(即所谓ellipsis
)或0
这种无作用的表达式,从而可加断点。 - 而比较好的做法是在VSCode中原本加断点的位置右键(如图),使用VSCode的条件断点功能。典型的是当满足某条件时中断。当然也有其它更强大的功能。
- 当然还可以使用高版本python的
breakpoint()
函数。
总结和问答练习
- Q: 像本文中一样用异常跳出多重循环可能有什么坏处?
A: 比如因为其他原因引起StopIteration
时也被文中的except
捕捉了。
为了解决这个可以自定义异常类型。 - Q: 从ExpRe[4]和[5],你对“生成测试数据”有何感想?
A: 随机生成数据可能由于概率原因无法覆盖一些情况。
对于输入有限制的情况(比如本题),如果随机生成数据可能会丢弃(浪费)大量数据(甚至有时检测是否符合约束本身就很费劲)。
如果人工生成符合约束的数据往往费时费力且分布“过于单一”难以考察各种情况。
因此使用约束求解等方法生成测试数据确实是有用的技术。 - Q: 解释文中错误发生的概率量级。
A: 错误概率显然为 1 / 100 1/100 1/100(l
为单元素,且恰好为[0]
, 1 / 10 ∗ 1 / 10 = 1 / 100 1/10*1/10 = 1/100 1/10∗1/10=1/100),因此循环100次通过的概率大致为 1 / e 1/e 1/e.
实验证明,当单元测试中每次循环100次时,通过和不通过的情况大概在同一数量级。
ExpRe[5] python[2] raise语句,条件断点相关推荐
- python 使用raise语句主动抛出异常(Exception)、将异常抛出给上一级
主动抛出异常 示例: 参考文章:使用Python提供的raise语句主动抛出异常 将异常抛出给上一级 示例: # -*- coding: utf-8 -*- """ @F ...
- python raise语句_Python异常处理,告别xxxxError!
程序在运行的过程中,产生了异常,这时,我们可能会有两种想法,第一种是针对这个异常做某些特殊的处理来进行程序的降级处理:第二种是希望程序忽略这个异常继续执行下去,这个异常可能并不干扰主逻辑的执行. 那这 ...
- python raise语句_python中异常报错的分析处理
想必到现在经过python基础的学习之后,小伙伴们都已经开始写很多脚本了,有大的有小的,但是有的时候并不是所写的能够顺利跑出结果来,期间会有不但的报错以及异常,很多我们都不理解,所以也就不会修改,这是 ...
- python中try...except的用法_python try...except语句、自定义异常、raise语句使用实例(异常处理的三种方法)...
异常处理,在编程中是必不可少的.错误难免会发生,用户不可能完全按照开发者的意愿行事,也有一些不可预知的错误,如网络请求等. 而程序一旦遇到异常,就会被终止,并且由底层抛出错误栈,无法按照计划顺利执行. ...
- 系统学习Python——异常处理:raise语句
如果要显式地触发异常,可以使用raise语句.它们的一般形式相当简单.一条raise语句的组成包括raise关键字,后面跟着可选的要引发的异常类或者异常类的一个实例: raise instance # ...
- python try exception类_Python异常-try、raise语句及自定义异常类
一.try语句 #try/except try: pass except: pass try: pass except Exception: pass #try/except... try: pass ...
- python基本语法语句-python学习笔记:基本语法
原标题:python学习笔记:基本语法 缩进:必须使用4个空格来表示每级缩进,支持Tab字符 if语句,经常与else, elif(相当于else if) 配合使用. for语句,迭代器,依次处理迭代 ...
- 深入理解Python的With-as语句
学习Python有一段时间了,最近做一个项目会涉及到文件的读取和关闭.比如:我想把一些对象序列化到文件里面,然后当我再次使用的时候,在从文件里面读取反序列化成对象.像这种操作一般都是用try-exce ...
- python raise_python raise 使用方法
是否可以在程序的指定位置手动抛出一个异常?答案是肯定的,Python 允许我们在程序中手动设置异常,使用 raise 语句即可. 读者可能会感到疑惑,即我们从来都是想方设法地让程序正常运行,为什么还要 ...
最新文章
- DailyTick 开发实录 —— UI 设计
- python怎么控制while循环_Python流程控制之while循环怎么学呢?老男孩Python
- sqlite java excel,Android将Excel表数据导入SQLite数据库
- linux 进程参数文件 /proc/pid/cmdline 简介
- curl 探测java网站_使用cURL查找网站重定向的位置?
- 区分 UML 类图中的几种关系
- mySQL的安装教程
- xxx定律-poj-3782
- 13-一对多左连接查询分步查询(查询所有客户及客户对应的订单)
- 125_Power BI 中 DAX 的性能测试
- sql截去最后一位_数据技能篇(EXCEL,SQL,Python)
- 在没有Docker容器的Ubuntu上安装SQL Server 2019
- android arm linux下使用内存转储crash工具分析 kernel system dump问题
- 【BZOJ5336】[TJOI2018]party(动态规划)
- 计算机的来源知识,计算机的由来计算机从诞生到现在才不过50多年的时间,可是发展却很快,已先后经历了四代,可以说是人丁兴旺。世界上第一台电子计算机1946年诞生于美国,名为埃尼阿克(ENIAC)...
- 计算机配置 主板,整套解决方案:I5-3470处理器和什么主板构成计算机配置?
- Python实现自由爆率抽奖小程序
- Linux各版本内核下载地址
- 【遇见Doris】Apache Doris 在京东广告平台的应用
- Chino with Rewrite
热门文章
- Python3爬虫图片抓取
- 卜若的代码笔记系列-unity系列-第三章:android交互之android studio(as)打jar包-5003
- gt和htd什么区别_同步带htd-3m和s3m区别是什么
- ▲ Android仿腾讯WiFi底部导航
- 笔记本清灰后组装后出现蓝屏,并不断的循环重启。
- Windows下安装 MongoDB
- 作为领导,如何既立威还不让下属反感?
- NVMe协议逻辑实现、nvme固态硬盘,支持master和slave两种模式,FPGA、SSD控制器,接口统一标准化、简单方便
- discuz要什么系统服务器,Discuz! Q安装,服务器要求详细说明
- 实验7-继承下的构造函数与析构函数