Python Tutor 可视化的深度思考

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

阅读: http://radar.oreilly.com/2015/08/learning-programming-at-scale.html

核心可视化工具 ( pythontutor.com ) 对很多人都有帮助。共享环境似乎也是一个很酷的想法,但我对其他工具没有任何具体评论。

虽然这看起来很酷,但我不是这种逐步可视化的忠实拥护者。这使用非常清晰的图形,看起来非常巧妙,它有一些局限性。我认为“可视化”的某些方面可能会产生误导。遵循特定初始条件的执行路径可能会掩盖不在正确路径上的事件和条件。目前尚不清楚一组陈述如何建立更一般的条件。

我是正式后置条件的粉丝。从这些,我们可以假设一个陈述,并计算出该陈述的最弱前提。当我们完成这个练习时,我们创建了一个正式的证明和一个程序。它非常优雅。它涵盖了一般情况,而不是具体示例。

最重要的是,这项工作取决于每个语句的形式语义。要编写代码,我们需要对语言中每个语句所做的一般状态变化有一个简洁的定义。我们正在查看每个语句的一般情况,而不是通过语句遵循特定的初始条件。

边栏:

在 C 中,这是做什么的? a[i++] = ++i;没有正式的定义。该语句声明了三个状态更改。但是它们是如何排序的呢?无论我们为 a[] 和 i 提供什么初始值,这仍然很模糊。调试器仅显示正在调试的特定实现。

可视化可以帮助一些人理解语句创建的状态变化。有些人确实通过观看这种“调试器”模式来学习东西。特别是,这可能会有所帮助,因为它具有比内置字符模式调试器更好的图形。

这个想法最适用于已经有意义的程序:设计良好的程序。从某个初始状态有序地进展到所需最终状态的程序。

学习者编写的程序可能并不那么干净。实际上,他们可能无能为力。他们甚至可能达到范围的尽头并且非常糟糕。

虽然这个工具在图形上很漂亮,但它仍然是一个调试器。它在一个内部世界中打滚,在这个内部世界中,形式语义可能会变得模糊。一般情况不容易显示。

我们这里有森林和树木问题。调试器(或其他逐条语句的可视化工具)强调每个单独的树。林间空地、灌木丛、树林、林分、刹车和矮林等较大的结构都看不见了。

不起眼的 while 语句(尤其是带有内部 if-break 的语句)作为单个语句可能非常难以理解。如果我们分解逐个语句的执行,则可以隐藏两个终止条件(一个在 while 子句上,一个在 if 子句上),因为可视化必须遵循特定的初始条件。

有了真正写得很好的教程——以及一些必要的元数据——超级可视化师可能能够突出显示存在的非快乐路径逻辑。这种替代路径查看可能有助于显示复杂逻辑的工作方式(和不工作。)

对于由学习者编写的程序——无能且没有适当元数据的程序——超级可视化者需要非常仔细地推理代码以确定存在哪些快乐路径和非快乐路径类型的逻辑。它必须定位并突出显示:

  • 自相矛盾的 elif 子句
  • elif 子句之间的差距
  • 缺少 else 子句
  • 极其复杂的 else 子句
  • 中断条件
  • 继续条件
  • 异常处理

对于真正糟糕的程序,超级可视化者可能会被难倒,不知道它的意图是什么。事实上,可能无法确定如何有意义地显示它以显示替代方案并显示特定代码如何概括为最终结果。


 def this_program_terminates(some_code):
    # details omitted

def demo(): while this_program_terminates(demo): print("w00t w00t")

这是做什么的?可视化工具如何帮助学生展示问题?

更进一步,我认为这种事情对于学习 Python 的函数式编程特性是如何工作的也可能是危险的。我认为公开生成器表达式的底层机制可能比简单地将其视为“惰性列表”更令人困惑。

这是很不错的。但它并不完美。支持对语句建立的一般后置条件进行推理的东西比具有出色图形的逐步调试器更有用。