是否可以在 Python 中使用与 Smalltalk(例如 Pharo)或 Common Lisp 中类似的工作流程?
Is it possible to have a similar workflow in Python as in Smalltalk (e.g. Pharo) or Common Lisp?
我非常喜欢在 Smalltalk 中可以进行的增量编程。您有一个 运行 程序,您可以在充实程序时向其中添加内容。您可以更改方法并在应用更改后重新启动堆栈以查看新版本的功能。当您的程序是 运行 时,您可以检查本地状态并更改它们。
在 Python 中是否有类似的东西?我已经看到了这种能力的暗示,例如 reload(),但我对 Python 的了解还不够,无法准确理解它的使用方式。我浏览了一些初学者 Python 书籍,但没有看到任何提及。
您可以即时更改函数定义。
例如,您有一个函数 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
我使用 ipython 进行交互模式 - 并且在编程项目完成之前保持终端打开,或者您可以通过 dill 保存会话(在 ipython 控制台中执行:!pip install dill
).
使用 dill 包保存会话
要保存所有全局变量和定义,请执行以下操作:
import dill
dill.dump_session('.session.pkl')
在新会话中您可以通过以下方式加载:
import dill
dill.load_session('.session.pkl')
取自here
有些事情是再怎么努力也做不到的Python。例如,在开发网络应用程序时,Flask/Django/Gunicorn 或诸如此类的网络服务器必须在源代码更改后重新启动其进程。但是在 Lisp 中,你在 REPL 中启动了一个 Web 服务器,你只需编译一个函数,例如添加一个新路由,你就可以立即尝试。没有重启任何进程,一切都更具交互性。
另一个示例是更新 classes 和实例。在 Common Lisp 中,假设你写了一个 class 并创建了一些对象。现在您更改 class 定义,并且现有实例得到(延迟)更新。例如,添加一个新插槽,删除一个插槽等。我们甚至可以控制更新的完成方式(通过子class一些通用函数)。
在Python中附加一个运行和远程进程是可以的,但是交互性要差很多,编辑体验也不太理想(愚蠢的python shell 在终端中默认 VS 一个完整的 Emacs,你可以在其中导航源代码并通过一次击键重新编译函数(C-c C-c
在 Slime 中)(或在任何其他可以连接到 Swank 服务器的编辑器中) ).
运行 一个给定的单元测试也很直接和快速,没有重新启动的过程。
参考文献:
内置方法exec(source_code, globals, locals)
接受 'globals' 和 'locals' 参数。
这些非常接近执行 'environment',或来自 smalltalk 的 'execution image'。
从 exec(..)
调用返回时,将声明的 class/function/variable 添加到 globals/locals。
globals/locals 可以很容易地存储到一个文件中,并用作未来执行的起始环境:)
模拟 smalltalk 'image based'。
我想这个技巧可以重现 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))
我非常喜欢在 Smalltalk 中可以进行的增量编程。您有一个 运行 程序,您可以在充实程序时向其中添加内容。您可以更改方法并在应用更改后重新启动堆栈以查看新版本的功能。当您的程序是 运行 时,您可以检查本地状态并更改它们。
在 Python 中是否有类似的东西?我已经看到了这种能力的暗示,例如 reload(),但我对 Python 的了解还不够,无法准确理解它的使用方式。我浏览了一些初学者 Python 书籍,但没有看到任何提及。
您可以即时更改函数定义。
例如,您有一个函数 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
我使用 ipython 进行交互模式 - 并且在编程项目完成之前保持终端打开,或者您可以通过 dill 保存会话(在 ipython 控制台中执行:!pip install dill
).
使用 dill 包保存会话
要保存所有全局变量和定义,请执行以下操作:
import dill
dill.dump_session('.session.pkl')
在新会话中您可以通过以下方式加载:
import dill
dill.load_session('.session.pkl')
取自here
有些事情是再怎么努力也做不到的Python。例如,在开发网络应用程序时,Flask/Django/Gunicorn 或诸如此类的网络服务器必须在源代码更改后重新启动其进程。但是在 Lisp 中,你在 REPL 中启动了一个 Web 服务器,你只需编译一个函数,例如添加一个新路由,你就可以立即尝试。没有重启任何进程,一切都更具交互性。
另一个示例是更新 classes 和实例。在 Common Lisp 中,假设你写了一个 class 并创建了一些对象。现在您更改 class 定义,并且现有实例得到(延迟)更新。例如,添加一个新插槽,删除一个插槽等。我们甚至可以控制更新的完成方式(通过子class一些通用函数)。
在Python中附加一个运行和远程进程是可以的,但是交互性要差很多,编辑体验也不太理想(愚蠢的python shell 在终端中默认 VS 一个完整的 Emacs,你可以在其中导航源代码并通过一次击键重新编译函数(C-c C-c
在 Slime 中)(或在任何其他可以连接到 Swank 服务器的编辑器中) ).
运行 一个给定的单元测试也很直接和快速,没有重新启动的过程。
参考文献:
内置方法exec(source_code, globals, locals)
接受 'globals' 和 'locals' 参数。
这些非常接近执行 'environment',或来自 smalltalk 的 'execution image'。
从 exec(..)
调用返回时,将声明的 class/function/variable 添加到 globals/locals。
globals/locals 可以很容易地存储到一个文件中,并用作未来执行的起始环境:)
模拟 smalltalk 'image based'。
我想这个技巧可以重现 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))