简介
Python [1] 是一种流行的编程语言。Python 和 Lua 通常被嵌入到应用程序中以提供脚本支持。
脚本在游戏中越来越频繁地使用。在选择脚本语言时,需要考虑许多因素。这可能是一个简单的决定,基于目标平台的架构,例如您是在 PC 上还是游戏机上。假设您有快速 CPU、虚拟内存和硬盘存储的奢侈,Python 的庞大库资源可以帮助您更快地完成项目。如果您没有这些奢侈品,Python 就不是一个选择,因为它相当大。
一般比较
以下是简单的比较,列出了 Python 和 Lua 相互的优势
Python
- 装备精良。庞大的非常有用的功能库。非常适合离线工作,例如工具脚本。庞大的示例脚本目录 [2]、教程 [3]、帮助 [4] 和一般参考材料 [5]。
- 通过实现真正的多维数组的附加模块,可以实现极高的性能数值计算(如科学和图形)。严格来说,Lua 没有数组,必须使用表结构来表示它们。
- Lua 数组是表,这是真的。但是,实现具有双重性质,并且数组使用(1..N 索引)应该被优化。 -ak
- 此外,Lua 必须使用表来表示数组并不完全正确。可以使用用户数据创建您描述的优化数组... Blue PiL 中有一个关于此的示例。 -nw
- ctypes(Python 2.4 中可用的模块,计划在 2.5 中包含在核心部分)允许访问现有的共享库(.so 或 .dll),而无需编写 C 包装器。
- 在 Lua 中查看 Alien 以获得此功能。 [6] -nw
- 有一个远程调试器 [7]。
- Lua 具有更简单但更简洁的语法(并且不可能变得更简单)。不过,差异并不大。比较 [9][10]。
- Python 对字符串和列表提供了丰富的切片功能,这极大地提高了生产力。我建议那些想要提高 Lua 生产力的人使用切片库。
- Python 拥有更广泛的 Unicode 支持(尽管并不完美)。
- Python 对空白敏感。经验丰富的 Python 开发人员知道,一旦克服了这感觉很奇怪的阶段,这就不再是问题。除了不是问题之外,它还有助于规范代码的外观,从而促进不同代码库之间的可读性。关于这会成为问题的 FUD 通常是由那些没有在日常工作中使用它的人传播的,正如在 Google 上进行一些抽样可以很容易地证明的那样。
- Lua 存在一个美化器,因此代码可以像 Python 一样轻松地“规范化”。 -SharkD
- 是的,但你并不被迫使用它。Python 强制你的代码至少看起来像样。这可是很大的区别。 —MR
- Python 内置了二元运算符(或、与、异或等)。嵌入式系统确实受益于这些,尽管 Lua 可以通过附加库或使用 LuaX 枚举来扩展以包含这些。
- Python 能够通过更严格的静态类型检查来减少错误。Lua 程序更容易出错,因为存在自动强制转换、访问未设置的变量而不抛出异常,以及必须检查大多数函数的 nil 值,而不是仅仅捕获异常。然而,这些方面中的一些可能存在一些优势。
- IMO 解决这个问题的唯一合理方法是静态分析。我大多数灾难性的全局变量类型错误都出现在不太常用的代码路径中,即使
-w
存在,它们也会在最糟糕的时候让用户崩溃。因此有了LuaLint,我想我应该为 5.1 试一试... --JayCarlson
- 这是一个关于更强/更弱[14] 类型,而不是静态/动态[15] 的问题。 -- xlq
- Python 拥有更多面向初学者的文档。Lua 仍然缺乏入门资料。
Lua
- 比 Python 更小巧。例如,看看 python22.dll 的大小,824kb。一个基本的 Lua 引擎,包括解析器/编译器/解释器,但不包括标准库,大小不到 100kb。
- 似乎缺乏对指针的任何使用或实现(引用?)。
- USERDATA 和 light USERDATA 怎么样?
- 这不是真的,所有表都是按引用传递的。只需将数据放在一个表中(甚至是一个表中的表),然后将其传递给函数。
- 更快的解释器(Lua vs. Python)和更快的 JIT 编译器(LuaJIT vs. Psyco) [17].
- 有一个很好的简单 API 用于在脚本和 C 之间进行通信,只需要很少的胶水代码生成。尝试在 Python 中创建和操作列表和字典,然后在 Lua 中执行此操作。
- 不使用引用计数来管理对象,这可能会变得复杂且容易出错。虽然你可以使用像 Python Boost 库这样的东西 [18],如果你喜欢 C++。
- Lua 最初是一个配置语言。这有一些很好的特点,因为它非常适合创建和配置事物 - 这是你在游戏中想要做的事情。
- 有一个很好、简单且非常强大的语法。我发现你可以在 Lua 中用比 Python 更少的代码写出相同的东西,并且由于 Lua 的元机制,你拥有更大的灵活性。例如,表在 Lua 中是列表和字典的组合(虽然你可以让它们表现得像 PythonLists 和 PythonDictionaries)。匿名函数也特别适合配置事物。在 Python 中,你会得到它们贫穷的表亲,lambda 函数。
- 代码库小巧、简单、稳定。如果需要,很容易在里面查看和修改。可能没有 Python 那样好地记录和注释。
- 真的没有那么容易查看。而且真的没有那么多注释。 -jv
- 我不同意。我发现查看 Lua 源代码并对编译器和 VM 进行更改非常简单。代码库非常干净,设计良好。 - bp
- 借助这本书,我发现代码库非常直观,易于修改。我经常将自定义的 Lua 引擎打包到我的软件中,而能够以最小的资源影响做到这一点对我来说非常有价值。- mw
- 很少有外部模块能让 Lua 更容易地打包用于特定目的,即使原始版本的功能少于所需。将此与 Python 的众多模块进行比较,这些模块包含标准发行版附带的库。
- Lua 支持多线程。多个 Lua 解释器可以存在于同一个进程中,并且每个解释器都可以独立地运行在自己的线程中。因此,Lua 更适合嵌入到多线程程序中。
- Lua 不区分空格。虽然与 Python 相比这有其缺点,但无需担心自动编辑器空格到制表符的转换,反之亦然。当使用等宽字体时,Lua 允许使用尽可能多的缩进,以使代码易于阅读。
- Lua 原生支持单个线程或进程中的多个线程和多个解释器。Python 不支持单个进程中的多个线程和多个解释器。多个线程可以访问 Python 解释器,但每个线程在这样做时必须持有全局锁。
- 这是错误的。全局解释器锁 (GIL) 如其名称所示是针对每个解释器的,而不是针对每个进程的;你确实可以在单个进程中嵌入多个解释器。 -JonathanEllis?
- 最初的作者是正确的,GIL 是针对每个进程的。你可以拥有多个解释器,但它们只是作用域问题,它们不允许多个并发线程运行。有关我找到的最简洁的讨论,请参阅 [19]。
- 但最初的作者在“Python 不支持单个进程中的多个线程和多个解释器”这一说法中仍然是错误的,这取决于你如何解释它。GIL 是针对每个进程的。你可以拥有多个解释器。你也可以拥有多个线程。这些线程可以在同一个或不同的子解释器中同时运行,这些子解释器位于同一个进程中。但是,当任何一个特定线程在 Python 代码中运行时,它将获取 GIL,这样做会锁定任何其他需要在运行时拥有 GIL 的线程。因此,尽管你可以同时拥有多个线程,但对于 Python 绑定的代码,你无法有效地并发运行它们。这意味着例如两个 Python 线程不能同时利用系统中的两个不同的 CPU 或内核。唯一例外是当 Python 代码进入 C 代码时,由于不需要 GIL,因此线程会释放它。此时,在 C 代码部分运行的线程可以与 Python 绑定的线程并发运行。因此,Python 扩展模块在调用 C 代码时,如果不需要,应该始终释放 GIL。包装了大量 C 库的 Python 扩展模块,其中数据与 Python 足够不同,允许释放 GIL,因此仍然可以观察到真正的并发性。
- 即使有上述更正,这也只适用于 CPython 解释器。其他 Python 实现(如 Jython、
IronPython
和 PyPy
)没有全局解释器锁。
- 最后一句话不正确;
PyPy
和 CPython 一样,也有 GIL。参见 [20]
- 不过,该语句的其余部分是正确的。GIL 的限制并非存在于所有实现中。它绝对不是
IronPython
的限制。我假设它在 Jython 中也不是限制,因为两者有很多相似之处,虽然我个人没有使用过 Jython。- KJR
- PyPy? STM 是一个没有 GIL 的 PyPy? 实现。-JKH
面向对象
基于 OO 模型的比较将在此处进行
Python
- 规定了面向对象编程的特定模型。Python 具有丰富的 OO 功能,包括元类、多重继承等等。
Lua
- 没有规定任何特定的 OO 系统。相反,你可以构建自己的(使用元方法)并根据自己的需要进行调整。
犹豫不决
- 它们都具有自动绑定生成器。SWIG 适用于两者。Lua 也有 toLua(它已经有一段时间没有开发了,但适用于 4.0 - 不确定是否适用于 4.1)。更新:现在有一个 toLua 5.0a,它运行良好!
- Lua 从 1 开始表格索引,这对于一种旨在与 C 接口的语言来说很奇怪,因为 C 中的数组从 0 开始。(评论:临时,使用索引 0 甚至 -1 并没有问题... 所以如果你是一个 C 程序员,你可以使用 "t[0]=t[-1]" 等等。但是如果你不是程序员... 例如,对于技术计算,你会觉得表格 t[1..n] 很熟悉)
- Lua 只处理一种类型的数字,通常是 C 双精度浮点数或浮点数,这会导致处理量过大。
- 你应该看看 Python 在添加两个整数时所做的工作,并思考一下什么是过度的处理。(例如,在 Python 中,每个不在 [-1, 100) 范围内的整数都是新分配的。)
- Lua 数字类型可以在编译时轻松更改为双精度浮点数、浮点数,甚至长整数或整数(如果有人不关心浮点数..)。但我同意,确实需要将整数和数字类型分开。 -ak
- ''Lua 5.3.x 引入了 int 子类型。
- CPython 解释器有一种名为 Cython [21] 的扩展语言,它使用与 Python 相同的语法和语义,但使用优化编译器将其转换为 C 代码。这允许通过与 Python 语言很好地集成的包装器轻松地与 C、C++ 和 Fortran 代码集成。这在 Lua 世界中是无与伦比的。Cython 还为 Python 代码提供了一条直接的优化路径,使其成为快速的手动优化计算代码,通常优于可用的 JIT 编译器。带有 LuaJIT 的 Lua 对于计算代码来说已经非常快,因此可能不需要这种手动优化路径。
参考资料
- Crystal Space [22] 支持这两种语言。提供的源代码可以提供有用的信息来帮助决定是否适合。更新:由于缺乏 swig,lua 可能停滞不前。
- Nebula Device [23] 也支持这两种语言,以及 TCL。
用户意见
请不要在这里开始一场口水战。请随时就您的经验发表简单的客观陈述。
- 我在哪里可以阅读有关 Lua 的“-w”选项的信息?谷歌没有找到任何结果。-- Alex
- 它不再存在。在 https://lua-users.lua.ac.cn/lists/lua-l/ 中搜索“lua -w”(带引号)。请参阅 DetectingUndefinedVariables。--DavidManura
- 恕我直言,我尝试过将两者都用于游戏和工具。Python 更适合离线工具,Lua 更适合嵌入和配置。Python 拥有大量对大多数任务非常有用的库,而 Lua 体积小、速度快且可配置性强,非常适合嵌入。-- NickTrout
- 所有内容在 Python 中都是分配在堆上的对象,包括数字。(因此 123+456 会创建一个新的堆对象)。我认为这可能是速度差异的重要原因。--JeffPetkau
- Lua 5.0 拥有出色的协程(或潜在函数,或者您称之为任何东西)支持,这对于游戏脚本非常重要。无栈 Python 也拥有它们,但它们从未进入核心。(这是我们选择 Lua 而不是 Python 作为引擎的*关键*问题。)--JeffPetkau
- 这是一个奇怪的观点,您将整个决定都建立在它之上。Python 的生成器与即将推出的 Lua 的有限协程相同。请参阅 LuaList:2002-07/msg00174.html。
- 它们是相关的,但并不相同。Lua 的协程更加通用。此外,我们并没有将整个决定建立在这个观点之上;它只是决定平衡的关键问题。
- 从历史上看,Python 生成器并不与协程“相同”:请参阅 https://www.pythonlang.cn/dev/peps/pep-0342/,了解 Python 最近支持协程的更改。
- 对于 Python,可以使用 Codespeak 库(Debian 包 python-codespeak-lib)中的 greenlets,无需使用完整的无栈路线,就可以获得非常好的协程支持。--SeanHoldsworth
- 但这真的对递归生成器有帮助吗?请参阅 LuaCoroutinesVersusPythonGenerators
- Python 似乎是(对我来说,一个正在为 Gary 的 mod 学习 Lua 并且是狂热的 Python 用户的人)Lua 几乎想要成为的东西,例如 Python 的一切都是指针的态度规则,它的导入而不是包含内容,以及您所做的一切都是对象的事实,有传言说它的内存管理非常...嗯,糟糕,但似乎 Python 3000 清除了这一点。
- 我将添加一个关于 Python 指针态度的说明,以及我还没有找到;嗯,Lua 做“引用”,它们...很奇怪,在 Python 中,人们仍然可以很容易地复制变量。
- 当您希望在代码中添加一个占用空间小的脚本引擎时,Lua 是理想的选择:就目前而言,它是可用的最小脚本引擎。我选择 Lua 来开发 Lixoo,一款 2D 冒险游戏引擎。我的目标之一是,一个可直接使用的 Lixoo 发行版(包括引擎和基本开发工具)的体积必须小于 1 兆字节。-- AdrianPerez
- Lua 拥有 Lisp/Scheme 的强大功能,但语法简单,实现也很好。我对 Lua 在嵌入式(实时)应用中的表现非常感兴趣。它的核心很小,设计灵活。特殊语言特性,例如对象中的状态依赖方法集,可以通过元表轻松实现。状态也可以保存在协程中。这些都是我在 Python 中希望拥有的功能。然而,Python 以其丰富的库、优秀的文档和优美的语法而著称。我不喜欢在每个代码块末尾使用 "end",我已经不习惯了 ;-) 最后但并非最不重要的是,一些错误会导致 Python 中的异常,例如除以零,无论数字类型(双精度/整数)如何,而我认为 Lua 在编译期间会捕获更多错误。但我认为 Python 会赶上来。像 PyChecker? 这样的工具已经可用,一些想法有望被整合到核心代码中。我喜欢这两种语言,并将其用于不同的目的。-- Dominic
- 我过去一直是,现在仍然是 Python 的忠实用户。然而,我从未在嵌入式场景中使用过 Python,因为我发现它太难用了。当我遇到 Lua 3.2 时,感觉有人打开了我的头骨,找到了我对 Python 嵌入的全部批评,然后用它来制作一种语言和环境,满足我的需求。
- 从那时起,我当然一直在使用 Python。我发现 Python 由于其庞大的库集,更适合通用脚本和 RAD 工作。我也非常习惯 Python 的语法,包括它的怪癖,所以发现我的手指自然而然地以 Python 的方式做事。(我在 Lua 中使用 "." 而不是 ":" 作为方法访问器的次数,会让大多数人笑掉大牙。)然而,即使是最轻微的可能性,我也不会考虑将 Python 用于任何嵌入式场景。Lua 是我在这方面的首选工具。-- MichaelRichter
- Pythonic 的方式是扩展而不是嵌入。在 Python 社区中,嵌入被认为是绝对不应该做的事情。(有关原因的简要说明,请参阅 http://www.twistedmatrix.com/users/glyph/rant/extendit.html。)Lua 很好地填补了 Python 避免的这个利基市场。另一方面,我认为 Lua 中的一些不错的动态库支持不会出错。(*我是这篇吐槽文章的作者,我不认为它一定反映了 Python 社区的普遍观点。我希望它能反映出来——我真的认为大多数嵌入只是迎合了 C 程序员的不安全感和误解,而不是满足了真正的技术需求。相关地,我一直期待着 Lua 意识到它是一种真正的编程语言,并停止围绕着这个“脚本”垃圾胡闹...*)(我不是这篇吐槽文章的作者,这是我第一次读到它应该“永远不做”。Blender、OpenOffice? 等等,肯定会明确表明这不是真的。您还可以阅读 [24] 来了解情况并非如此)。
- 我广泛使用 Python 进行游戏开发,我认为如果您正在寻找一种可以轻松嵌入到您的引擎中以创建实体逻辑或配置/调整脚本的语言,Lua 可能是一个更好的选择。Python 是一种功能强大的通用语言,在集成复杂性、性能和内存需求方面,您将为此付出代价。但是,如果您正在寻找一种可以替代 C 或 C++ 在您的许多模块中使用的生产力高的语言,Python 明显是更好的选择(如上所述,这在 Python 中通过扩展而不是嵌入来完成更好)。Lua 是为小型脚本而设计的,在大型开发方面无法与 Python 相比。-- Camelo
- 我刚接触脚本,我打算在选择一个用于我的 3D 游戏引擎的脚本之前比较不同的替代方案。我花了三个小时让基本的 Lua 5 嵌入和扩展工作起来。我心想,“这个脚本东西并不难!”,然后转向 Python。四天后,在经历了 Python C-API 的痛苦和沮丧之后,试图让 Boost.Python 与 Python 2.3 编译,尝试 CXX 和 SWIG 以及上帝知道什么,并试图让它们在 Visual Studio 6 下使用 windows.h 运行(这导致了多个相互不兼容),我找到了 luabind,我认为我再也不会回头使用 Python 了。-- Mike
- 给 Mike 的评论:虽然我从未使用过它,但 Boost.Python 不适用于 Python 2.3,而是适用于 2.2。请参阅 [25]。-- Thomas
- 我不确定这个引用是什么时候做出的,但是您现在可以轻松地切换 Boost.Python 编译的 Python 版本。但是,我发现 Python 嵌入起来有点痛苦。最值得注意的是,它的全局解释器锁机制对于多线程 C++ 应用程序来说有点麻烦。
- Boost.Python 1.33.1 新闻:构建现在默认假设 Python 2.4,而不是 2.2。-- 匿名捐赠者?
- Python 的作用域,即使是“新的”嵌套作用域,也非常有限且容易出错。循环和类似的结构不会打开新的作用域,因此无法在其中创建私有变量。例如,如果您在循环中创建了一个与循环之前某个变量同名的变量,就会覆盖外部变量。在 Python 中,除了注意名称冲突或使用大量嵌套函数来打开新的作用域之外,别无他法。相比之下,Lua 在这种情况下为您提供了精确的控制:在循环中,您可以使用 `local` 创建私有变量,也可以省略它并写入外部变量。--JohnBelmonte
- 根据我的经验,将变量隐藏在外部作用域中是容易出错的,而 Python 阻止了这种情况。在单个函数中,单个名称引用两个不同的对象,这肯定会让人困惑。事实上,许多 C++ 风格指南建议不要隐藏这样的变量。Python 强调可读性,禁止这种行为实际上是朝着这个方向迈出的一步。-- 匿名捐赠者?
- 在 C# 中,以这种方式隐藏变量是一个错误。我喜欢这样 - 我希望编译器通知我任何歧义,并让我消除歧义(通过使变量名称在函数内唯一)。-- BjarkeDahlEbert
- 是的,将变量隐藏在外部可能会成为问题,但我们每个人都喜欢为变量使用描述性名称,所以最终你会遇到这样的问题:我无法使用 `value_index` 这个名称,因为它在上面被使用过,我需要输入 `local_value_index`,最终我们找到了 Lua 使用的解决方案。
- 我刚开始学习这两种语言,但我认为这两种语言都非常强大,但它们的功能不同。我认为 Python 和 Lua 之间的区别与 Java 和 C 之间的区别相同。就像 Java 一样,Python 庞大,拥有庞大的库,速度相当慢,但使用起来非常方便,可以实现很多功能。另一方面,就像 C 一样,Lua 轻量级,几乎在所有平台上都实现了,但对用户在设计方面的帮助较少。-- Xavier
- 我花了不少时间研究要在 C++ 程序中嵌入的脚本语言,最终选择了 Python 或 Lua。在花了一天多的时间尝试让 boost.python 工作后,我放弃了,因为我甚至无法让一个简单的 Hello World 程序用 bjam 编译。除此之外,我还没有找到一个合适的方法来将一些全局变量(指向 C++ 类的指针)添加到 Python 解释器中,也不喜欢 boost.python 的语法或实现虚函数的方法。总之,我决定花几个小时看看我能用 Lua 和 tolua++ 做到什么程度,我能够公开所有公共方法和变量,在数十个类中,一切都按预期工作。是的,虚函数实现不起作用,我无法从 C++ 接口派生来创建一个新的 Lua 类,但我可以接受。两者都不是完整的解决方案,但任何东西都比在 C++ 中实现这一切要好。--Tom
- 对于所有在 Python 中使用 SWIG 或 Boost 等工具遇到困难的人,我发现
PyInline
[26],它就像魔法一样。我只需要用一些 C 代码创建一个字符串,调用 "make",我就可以得到可调用的 Python 函数!它在 XP 和 Fedora 上运行良好,使用完全相同的源代码。关于包含有一些怪癖,但对于简单的粘合到 .so 或 DLL,它非常棒。也就是说,我正在寻找一种超小的核心可嵌入语言,用于一些机器人技术的东西,到目前为止,Lua 看起来非常不错。
- 那些抱怨 Python-C API 危险性的人应该看看 Pyrex。我自己还没有用过它,但我认为我最终会在我即将到来的游戏中使用它。它具有 Pythonic 语法,但可以使用 C 数据类型,因此你可以更容易地为 Python 编写 C 模块。当然,这仍然是扩展 Python 而不是嵌入它。如果我发现我没有使用 Python 的许多附加功能或稳定性,我可能会使用 Lua 代替。
- 使用最适合工作的工具。如果我想做一个一次性的独立程序来进行一些字符串操作(通常是为了支持我妻子的生意),我会使用 Python。对于向大型嵌入式系统添加脚本功能,Lua 更好一些。对于编写大型复杂程序,C++ 是我的首选工具。对于修改或添加 WordPress? 网站的功能,PHP 是阻力最小的路径,但我发现自己希望有人用 Python 重做这个烂摊子。
另请参见
最近更改 · 偏好设置
编辑 · 历史
最后编辑于 2018 年 9 月 19 日下午 3:54 GMT (差异)