Python中是否有可能拥有与Smalltalk(例如Pharo)或Common Lisp中类似的工作流程



我非常喜欢在Smalltalk中可以进行的增量编程。你有一个正在运行的程序,当你充实你的程序时,你会添加到它中。您可以更改方法,并使用所应用的更改重新启动堆栈,以查看新版本的功能。当程序运行时,您可以检查本地状态并更改它们。

类似的东西在Python中可能存在吗?我已经看到了这种能力的暗示,比如reload((,但我对Python的了解还不够,无法确切理解它是如何使用的。我看过一些Python初学者的书,但没有看到任何提到这一点。

无论在Python上付出什么努力,有些事情都是不可能的。例如,在开发web应用程序时,Flask/Django/Gunicorn或whatnot web服务器必须在源代码发生更改后重新启动其进程。但在Lisp中,您在REPL中启动一个web服务器,只需编译一个函数,例如添加一个新路由,就可以立即尝试。没有重新启动任何进程,它更具互动性。

另一个例子是更新类和实例。在Common Lisp中,假设您编写了一个类并创建了一些对象。现在您更改了类定义,并且现有实例得到了(延迟(更新。例如,添加一个新插槽,删除一个插槽,等等。我们甚至可以控制更新的方式(通过子类化一些通用函数(。

在Python中附加到一个正在运行的远程进程是可行的,但交互性要低得多,编辑体验也不太理想(默认情况下,终端中的一个愚蠢的Python shell与一个完整的Emacs相比,在这里你可以一键导航源代码并重新编译函数(Slime中的C-c C-c((或在任何其他可以连接到Swank服务器的编辑器中((。

运行一个给定的单元测试也是简单而快速的,没有重新启动的过程。

参考文献:

  • https://lispcookbook.github.io/cl-cookbook/clos.html
  • 在另一台计算机上调试正在运行的程序:https://lispcookbook.github.io/cl-cookbook/debugging.html#remote-调试

我使用ipython进行交互模式,并且在编程项目完成之前保持终端打开,或者您可以通过dill保存会话(在ipython控制台do:!pip install dill中(。

使用dill包保存会话

要保存所有全局变量和定义,请执行以下操作:

import dill       
dill.dump_session('.session.pkl')

在新会话中,您可以通过以下方式加载:

import dill
dill.load_session('.session.pkl')

它是从这里

您可以随时更改函数定义。

例如,您有一个函数mymodule.myfunc(x,y),您想看看long_process()是如何调用它的。

您可以(在REPL>>>提示下或在笔记本中(

myfunc_orig = mymodule.myfunc
def myfunc_new(x,y):
print("myfunc_new",x,y)
return myfunc_orig(x,y)
mymodule.myfunc = myfunc_new
long_process()

现在,每次调用mymodule.myfunc时都会得到一个打印输出。

当你完成后,你用恢复它

mymodule.myfunc = myfunc_orig

内置方法exec(source_code, globals, locals)接受"globals"one_answers"locals"参数。这些非常接近smalltalk中的执行"环境"或"执行图像"。

声明的类/函数/变量在从exec(..)调用返回时被添加到全局/本地。

全局/本地可以很容易地存储到一个文件中,并用作未来执行的启动环境:(

这模拟了"基于图像"的闲聊。

我想这个技巧可以重现smalltalk执行环境的属性,是真的吗?

示例:

locals, globals = {}, {}
exec("""def f(x): return x+1""", globals, locals)
print(locals["f"](2))
exec("""def f(x): return x+10""", globals, locals)
print(locals["f"](2))

相关内容

  • 没有找到相关文章

最新更新