Python与Smalltalk的元编程能力比较

10 投票
2 回答
1594 浏览
提问于 2025-04-16 22:24

最近我在学习Python,发现它的运行时元编程能力真是太棒了。之前我在阅读关于Smalltalk的资料时,第一次听说“运行时元编程”这个词。根据我所知道的,Smalltalk在这方面的能力是最强的。那么,Python在元编程方面和Smalltalk相比怎么样呢?这两种语言在处理元编程时有什么显著的不同呢?

2 个回答

10

根据提问者的要求发布的回答。

Smalltalk 这个编程语言有一个很重要的概念叫做“正交性”。简单来说,就是不同的功能应该能够互相配合使用。而老实说,Python 在这方面就有些不足。并不是所有的功能都能在所有的情况下使用。下面是一些例子:

  • inspect.getargspec() 这个功能不能用在内置函数上,或者在调用 functools.partial 后的结果上(在 C 解释器中是这样)。
  • eval 只能处理表达式字符串,而 exec 只能处理语句字符串。
  • Lambda 表达式不能被序列化(也就是不能保存成文件等)。
  • myclass = type('x', (object,), {'__init__': partial(foo, value)}) 生成的类不能被实例化,而如果用一个等效的 lambda 表达式代替 partial 就可以正常工作。(不过这可能只是个bug,而不是特性。)

也许 PyPy 没有这些问题,我不太确定。但我真的很喜欢 Python,觉得在实际应用中使用元类、柯里化和偶尔的描述符非常方便。

12

在这方面,Python的表现其实还不错。Smalltalk通常不太区分程序和元程序,但Python在这方面更明确,比如有专门的语法来使用装饰器,或者用__foo__()这种命名方式来处理元编程。这是件好事。

不过,这两者的比较有点像苹果和橘子的对比。Smalltalk是一种更小、更紧凑的语言,所以可以用来做元编程的东西就少一些。举个例子,__getattr__()是一个钩子,允许Python对象自定义属性访问的实现。而Smalltalk没有类似的东西。但是!Smalltalk对对象内部状态的封装更严格,没有像Python那样的object.attribute语法。因此,要读取对象的状态,就得通过一个方法来实现……而这正是__getattr__()所提供的功能。所以在很多需要用__getattr__()的情况下,你在Smalltalk中只需写一个普通的方法就可以了,不需要元编程。

这种情况在很多地方都存在:Python的__getitem__()等功能让你可以写出像列表或字典那样的类。而Smalltalk不需要这样,因为数组和字典都是普通的Smalltalk类,使用它们没有特别的语法。Python的__eq__()等功能支持运算符重载,而Smalltalk没有运算符,所以你可以直接实现+而不需要特别的处理。Python的contextlib提供了一些方便的工具来实现你自己的上下文管理器。虽然Smalltalk没有with这种结构,但它有非常简单的语法来处理lambda表达式,这样你也能以简单的方式实现类似的功能。

Smalltalk的元编程功能通常比较底层。比如,你可以创建自己的CompiledMethod实例,并把它们放进一个类的方法字典里。你还可以写自己的编译器,并指定某个类的所有方法都用这个编译器来编译。这能实现很多有趣的功能——我见过一些项目尝试不同的语法,给字节码加上分析工具,捕捉对实例变量的读写以实现透明持久化等等。

Smalltalk的元编程功能很强大,但它们的组织方式没有Python那么整齐,而且使用频率也不高。

撰写回答