Python与Smalltalk的元编程能力比较
最近我在学习Python,发现它的运行时元编程能力真是太棒了。之前我在阅读关于Smalltalk的资料时,第一次听说“运行时元编程”这个词。根据我所知道的,Smalltalk在这方面的能力是最强的。那么,Python在元编程方面和Smalltalk相比怎么样呢?这两种语言在处理元编程时有什么显著的不同呢?
2 个回答
根据提问者的要求发布的回答。
Smalltalk 这个编程语言有一个很重要的概念叫做“正交性”。简单来说,就是不同的功能应该能够互相配合使用。而老实说,Python 在这方面就有些不足。并不是所有的功能都能在所有的情况下使用。下面是一些例子:
inspect.getargspec()
这个功能不能用在内置函数上,或者在调用functools.partial
后的结果上(在 C 解释器中是这样)。eval
只能处理表达式字符串,而exec
只能处理语句字符串。- Lambda 表达式不能被序列化(也就是不能保存成文件等)。
myclass = type('x', (object,), {'__init__': partial(foo, value)})
生成的类不能被实例化,而如果用一个等效的lambda
表达式代替partial
就可以正常工作。(不过这可能只是个bug,而不是特性。)
也许 PyPy 没有这些问题,我不太确定。但我真的很喜欢 Python,觉得在实际应用中使用元类、柯里化和偶尔的描述符非常方便。
在这方面,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那么整齐,而且使用频率也不高。