show | version | enable_checker |
---|---|---|
step |
1.0 |
true |
- 上次我们定义了函数
- 函数就是一个套路、流程、惯用方法
- 我们可以把他定义出来
- 然后再调用
- 调用函数
- 定义函数就是把相关的代码封装到一个函数里面
- 以后只要调用函数
- 相关的代码
- 就从头到尾地执行了
- 这个函数可以调试么?🤔
- 我们改写一下代码
- 加上输出语句
- 在调用函数前后
- 在进入函数时、退出函数前
- 尝试运行
- 运行过程和你想象的一样么?
- 这个应该怎么理解呢?
-
前面只是定义函数并不执行
-
主程序从第7行往下执行
-
遇到sorry函数调用
-
跳转到第1行
- sorry函数定义的位置
- 然后顺序执行sorry函数
- 执行完成后跳转回调用程序的位置
-
继续第9行
-
然后程序全部执行完毕
-
我们可以debug进去么?
- 首先是定义函数
- 一开始没有定义的时候
- 不认sorry函数
- def之后
- 就认了
- 函数究竟是什么?
- 函数名也是一个对象的引用
- 是一个function类对象的引用
- 也有相应的地址
- 然后我们继续
- 一路n下去
- 在执行程序的时候
- 把函数作为一个整体
- 没有一步步地调试
- 一次性把sorry()都执行完成了
- 可以进入到函数内部一步步地执行么?
- 但是这个断点好使么?
- 一路continue到断点
- 确实可以进入到sorry函数内部了
- 但是走到第5句之后会如何呢?
- 跳出函数
- 注意那个return
- 第一个return是从sorry函数结束后
- 从sorry函数中return出来
- 回到主程序
- 第二个return是主程序结束
- 除此之外,还有什么关于函数跳转的命令么?
- 我们去试试
- 当播放头运行到函数调用的这一句的时候
- step into
- 进入了被调用的函数当中
- 一步步调试执行
- 那怎么知道我究竟在哪呢?
- bt和w(here) 都对应着
print_stack_trace
- w(here) 查询当前播放头所在位置
- w可以告诉我,我在哪!!!
- bt的意思是bottom 看的也是当前位置
- w(here) 查询当前播放头所在位置
- 这个就是函数堆栈的样子
- 是一层层调用的关系
- 怎么理解呢?
- 这个堆栈总共分成四层(红、绿、蓝、紫)
- 堆栈的顶在红色部分
- 是sorry函数中第4行
- 谁调用的sorry函数呢?
- sorry.py中的第8行(绿色部分)
- 调用了sorry函数
- 谁调用的sorry.py呢?
- exec(cmd,globals,locals)(蓝色部分)
- 调用了sorry.py
- 谁调用了exec函数呢?
- bdb.py(580行)的run函数(紫色部分)
- 是在堆栈(Stack)最底下
- 函数就是这样层层调用的
- step进去后可以进函数内部调试
- 出了错也是一层层地找到位置
- 比如
- 我们打开一个不存在的文件的时候
- 明明只出了一个错误
- 为什么给我这么多行提示?
- 因为报错输出了跟踪(Traceback)的过程
- 错误发生在一个具体的位置
- 是open函数的层层调用时候执行的一句
- 离我们对于open函数的调用很远
- 要一层层地跟踪(Traceback)
- 找到我们代码的错误位置和类型
- 调试的时候可以跳出函数么?
- r和return就是返回
- 跳出当前函数
- 返回到调用他的那一层
- 试试
- 红圈里面的r直接跳出函数
- r代表return
- 把345句都执行完了
- 然后返回到第9句的位置
- 第9句跳出后返回到调用这个sorry.py的位置
- 这样就可以
- 深入函数
- 跳出函数了
- 我们可以从指令的角度观察一下吗?
- 指令分两大块
- 红色的是主程序
- 0,6字节是函数sorry的声明(declaration)
- 8,16字节是函数sorry调用
- 黄色部分是sorry函数
- 0,6字节是输出老婆我错了
- 8,18字节是输出都是我不好
- 虽然这个东西看起来很复杂
- 但是对于我们来说很简单
- 就像灯装好了之后
- 一拉灯绳
- 就亮了
- 我们先去总结一下
- 这次我们调试了自己定义的函数sorry
- 调试有这样一些命令
- step
- 跳入当前行所在函数
- return
- 跳出当前函数回到调用的位置
- where
- 告诉我现在执行到了哪里
- 当前播放头的程序栈位置
- step
- 有了这样一些命令
- 我们就可以更好地调试python程序了
- 可以完成一些更复杂的套路么?🤔
- 我们下次再说!👋