![]() |
1
2
总结 :这是编写编译器的一种常见方法,这里就可以了。
在其他语言中处理这个问题的一个非常常见的方法是“模式匹配”,这正是您所描述的。我想这就是它的名字
问题是,这种编程语言实现的常见习惯用法是Python中的反模式。哦,哦。正如你可能知道的,这更像是一个政治问题,而不是一个语言问题。如果其他的pythonistas看到代码,他们会尖叫;如果其他语言实现者看到代码,他们会立即理解。 这在Python中是反模式的原因是因为Python鼓励使用duck类型的接口:您不应该基于类型拥有行为,而是应该由对象在运行时可用的方法来定义行为。 S. Lott's answer 如果您希望它是惯用的Python,那么它可以很好地工作,但它添加的很少。
我怀疑您的设计并不是真正的duck类型化的——毕竟它是一个编译器,并且使用一个名字定义的具有静态结构的类非常常见。如果愿意,可以将对象视为具有“类型”字段,并且
Addenum: 模式匹配可能是人们喜欢用函数语言编写编译器等的首要原因。 |
![]() |
2
2
在python中有一个经验法则,如果你发现自己编写了大量的if/elif语句,并且有类似的条件(例如,一堆isinstance(…)那么你可能是以错误的方式解决了这个问题。 更好的方法包括使用类和多态性、访问者模式、dict查找等。在您的案例中,使具有不同类型重载的operator类可以工作(如上所述),具有(类型、运算符)项的dict也可以工作。 |
![]() |
3
2
对。 不用实例,只要使用 Polymorphism . 这更简单。
这种方法很简单,从不需要
在需要强制的地方,这样的事情怎么样?
这仍然是一个多态性问题。
|
![]() |
4
1
文章没有攻击
是的,还有更好的方法。或几个。例如,可以将类型的处理转化为函数,然后通过查找每个类型来查找正确的函数。这样地:
如果您不想自己做这个注册表,您可以看看Zope组件体系结构,它通过接口和适配器来处理这个问题,这真的很酷。但这可能太过分了。 更妙的是,如果您能以某种方式避免进行任何类型的类型检查,但这可能很棘手。 |
![]() |
5
0
在我使用python 3编写的DSL中,我使用了复合设计模式,因此节点的使用都是多态的,正如S.lott推荐的那样。
但是,当我首先在输入中读取以创建这些节点时,我确实使用了很多IsInstance检查(针对诸如Collections.Iterable等抽象基类,Python3提供了这些基本类,我相信它们在2.6中),以及对hasattr的检查。
将isInstance用于此类测试比使用type()更为普遍,因为isInstance将捕获子类——如果可以对抽象基类进行测试,那就更好了。参见 http://www.python.org/dev/peps/pep-3119/ 有关抽象基类的信息。 |
![]() |
6
0
在这种特殊情况下,您似乎正在实现的是一个运算符重载系统,它使用对象类型作为您要调用的运算符的选择机制。您的节点类型恰好与您的语言类型相当直接地对应,但实际上您正在编写一个解释器。节点的类型只是一段数据。 我不知道人们是否可以将他们自己的类型添加到特定于域的语言中。但我还是建议采用表驱动的设计。 创建一个包含(binary_operator、type1、type2、result_type、evalfunc)的数据表。使用isInstance在该表中搜索匹配项,并有一些条件来优先选择某些匹配项。也许可以使用比表更复杂的数据结构来加快搜索速度,但现在基本上,您使用的是ifelse语句的长列表来进行线性搜索,所以我敢打赌,一个普通的旧表将比您现在所做的略快。 我不认为IsInstance在很大程度上是错误的选择,因为类型只是您的解释器用来做决定的一部分数据。双重分派和其他类似的技术只会掩盖你的程序正在做的真正的工作。 在Python中,一个简洁的地方是,由于运算符函数和类型都是第一类对象,所以您可以直接将它们填充到表中(或者您选择的任何数据结构)。 |
![]() |
7
-1
如果您需要对参数(除了接收器)进行多态性,例如,要使用示例中建议的二进制运算符处理类型转换,可以使用以下技巧:
|
![]() |
dallin · 数组中的逗号运算符是否有名称? 11 年前 |