我正在用python编写一个预处理器,其中的一部分用于AST。
有一个render()
方法负责将各种语句转换为源代码。
现在,我有这样一个(简称):
def render(self, s):
""" Render a statement by type. """
# code block (used in structures)
if isinstance(s, S_Block):
# delegate to private method that does the work
return self._render_block(s)
# empty statement
if isinstance(s, S_Empty):
return self._render_empty(s)
# a function declaration
if isinstance(s, S_Function):
return self._render_function(s)
# ...
如您所见,它很乏味,容易出错,而且代码很长(我有更多种类的语句)。
理想的解决方案是(在Java语法中):
String render(S_Block s)
{
// render block
}
String render(S_Empty s)
{
// render empty statement
}
String render(S_Function s)
{
// render function statement
}
// ...
当然,python不能这样做,因为它有动态类型。当我寻找如何模仿方法重载时,所有的答案都只是说“你不想在python中那样做”。我想这在某些情况下是正确的,但是这里kwargs
一点用处都没有。
如果上面所示的类型检查ifs,那么在python中,如果没有长达一公里的可怕序列,我将如何做到这一点?另外,最好是用“Python式”的方法?
注意:可以有多个“Renderer”实现,它们以不同的方式呈现语句。因此,我不能将呈现代码移到语句中,而只调用s.render()
。必须在renderer类中完成。
(我找到了一些interesting "visitor" code,但我不确定它是否真的是我想要的东西)。
想要这个吗?
将对类对象的引用保留为字典中的键,并将其值设置为要调用的函数对象,这将使代码更短,更不容易出错。这里唯一可能出错的地方是字典的定义。或者你的内在功能。
您正在寻找的重载语法可以使用Guido van Rossum's multimethod decorator来实现。
这里是multimethod decorator的一个变体,它可以修饰类方法(原始的修饰纯函数)。我将变量命名为
multidispatch
,以消除与原始变量的歧义:它可以这样使用:
上面的演示代码显示了如何根据参数的类型重载
Foo.render
方法。这段代码搜索完全匹配的类型,而不是检查
isinstance
关系。可以修改它来处理这个问题(代价是查找O(n)而不是O(1)),但是因为听起来你不需要这样做,所以我将把代码放在这个更简单的格式中。如果您使用的是Python3.4(或者愿意为Python2.6+安装backport),那么可以使用^{} 来完成以下操作:
输出:
*基于this gist.的代码
相关问题 更多 >
编程相关推荐