Python中为什么很少使用回调(callback)而JavaScript中却到处都是?
null
Python中为什么很少使用回调(callback)而JavaScript中却到处都是?
python 完全可以写 callback,js 是不得不写 callback,本质的原因是 js 的调度模型是事件驱动的,必须把事件行为提前注册
这个问题问得挺有意思,确实是个常见的困惑。核心原因在于两种语言默认的“编程范式”和运行时环境不同。
JavaScript(特指浏览器和Node.js环境)从出生起就是单线程事件驱动的。它只有一个主线程,为了不阻塞UI或后续操作,所有I/O(比如网络请求、文件读取、定时器)都是非阻塞和异步的。代码执行时,遇到异步操作,JS引擎不会停下来等结果,而是继续执行后面的代码。那异步操作的结果谁来处理呢?答案就是回调函数。引擎在将来某个时刻(比如数据返回了、定时器到了)会把对应的回调函数推入“任务队列”,等主线程空闲时再执行它。所以,回调是JS处理异步操作的基础机制,自然到处都是。
Python虽然也支持异步编程(asyncio),但它的默认和主流模式是同步、多线程/多进程。在同步模式下,代码顺序执行,写起来直观。即使要做并发,传统上更倾向于使用threading或multiprocessing模块来开启多个线程或进程,每个线程/进程内仍然是同步代码。在这种范式下,回调并不是必需品。
那Python里什么时候会用回调呢?主要在一些事件驱动的框架或库中,比如GUI库(Tkinter, PyQt的信号/槽机制本质上是一种更结构化的回调)、Twisted网络框架、或者一些底层的事件循环设置。但在日常的脚本、Web后端(如Django, Flask同步视图)、数据处理中,你更常看到的是顺序执行的代码、for循环、或者用concurrent.futures来管理并发,而不是层层嵌套的回调。
所以,简单说:JS是“不得不”用回调来处理其核心的异步模型;Python则拥有更多同步和并发的选择,回调只是其中一种,并非默认或最常用的模式。
总结:语言设计初衷和主要应用场景决定了各自的代码风格。
JavaScript 是配合网页使用的时候回调才多吧? Python 程序的架构一般是从头执行到尾结束的。而网页中 JavaScript 不是这样,是根据事件来执行的,所以需要回调。
js 事件驱动 必须写 callback
python 如果是事件驱动也要 callback 的
https://www.tornadoweb.org/en/stable/iostream.html#tornado.iostream.BaseIOStream.write
Python 当年著名的库,同样回调地狱。
当然,Python 3.5+ 拥抱 async 了,就没有回调地狱了。
能把函数赋值给变量,都可以产生这种现象
因为 python 有多线程和协程可以用
不是特别了解,不过 callback 不是异步的时候才用的么?
Python 的异步处理不是强项,所以用得少么?
twisted 就是回调
Python 当然有 callback,任何事件驱动的框架都或多或少需要。但为什么很少有”长得像 callback hell 的代码”,有一点很实际的:python 的匿名函数故意设计成不支持多行的,闭包捕获也设计成受限的形式, 所以要求你每次想传一个不方便在一行内表达的函数,就得起个名字。python 程序员或许称之为 pythonic,进一步可以参考下 GvR 为什么要这样设计。
即使是 java 这样的语言,遇到大量复杂的事件场景,依然会出现 Handler.OnEvent(event e) 这样的设计,这种形式与提供轻量级的 callback 相比是各有优劣的。
从语言本身来说,越是依赖于把一块有名字的内存改来改去的语言 /范式,可能越适用于前者,因为这种语言的捕获往往是 bugprone ( by ref,需要解决生命周期或者作用域) / poor perfomance ( by copy ),一般需要专门有个框架来给你处理这种事。当然有的语言和平台直接把框架做进基础库了。
而对 closure,pure function 等概念有精良设计的语言,就可以鼓励程序员多用 callback。括号就可以叠很多层。
还有一些觉得程序员很聪明的语言,会把这两种方式都拿出来给你用,你自己去管理到底怎么用 closure,到底用哪种方式。所以这些语言的程序员就可以把它们搅和在一起,写出彼此都看不懂的代码。
现在我们发现大部分程序员其实没有那么聪明,只能写好同步的代码,于是现代语言纷纷加上了 async 关键字,这样你就可以用同步的方式写异步的代码了(理想)。这件事的一个积极意义在于,大家终于发现自己一直在用扭曲的方式实现本来就应该由编译器 /runtime 干的事。
人家这叫“高阶函数”
你如果用 python 写 gui,也是事件驱动型,一样要写回调,不过在 qt 中不这么叫,叫信号和槽。


