深入 PEAK 的新特性
2007-03-29 12:16:36 来源:WEB开发网清单 5. 交叉条件中的模糊性
@doIt.when('foo < 10 and bar < 100')
def doIt(foo, bar):
print "Condition 1 |", foo, bar
@doIt.when('foo < 100 and bar < 10')
def doIt(foo, bar):
print "Condition 2 |", foo, bar
doIt(50,5) # -> Condition 2 | 50 5
doIt(5,50) # -> Condition 1 | 5 50
doIt(5,5) # -> raises dispatch.interfaces.AmbiguousMethod
这就变成难以调试的程序逻辑了。
封装分派函数
用来降低可能出现的断言模糊性的一种方法是将应用程序的条件分解为单独的通用函数。PEAK 的 dispatch 就提供了一种类似的功能,可以显式地将 next_method 分派到 gnosis.magic.multimethods 或 CLOS 中。
在本文中我们并不会详细介绍 next_method 方法;相反,让我们来集中介绍更加通用的一种对 primary 通用函数进行封装的技术,它可以在前置或后置条件(在 primary 函数之前或之后调用的方法)中使用。另外,与 primary 条件不同,doIt.before() 和 doIt.after() 条件都可以执行多个满足条件的断言。这就与我们在调用 main 之前需要确认的很多前置条件的概念吻合了。在出现模糊性的情况中,执行顺序是任意的(它使用了定义的顺序)。
下面是 doIt() 例子的一个变种,它看起来更加清晰(见清单 6):
清单 6. 前置条件和后置条件的分派
import dispatch
@dispatch.generic()
def doIt(foo, other):
"Base generic function of 'doIt()'"
@doIt.before("isinstance(foo,int)")
def sayType_int(foo, other):
print "foo is an int |",
@doIt.before("isinstance(foo,float)")
def sayType_float(foo, other):
print "foo is a float |",
@doIt.when("3<=foo<=17")
def doIt(foo, other):
print "foo is between 3 and 17 |",
@doIt.when("0<=foo<=1000")
def doIt(foo, other):
print "foo is between 0 and 1000 |",
@doIt.when(dispatch.strategy.default)
def doNothing(foo, other):
pass
@doIt.after("True")
def sayValues(foo, other):
print foo, other
doIt(-17, 'x') # -> foo is an int | -17 x
doIt(1.1, 'x') # -> foo is a float | foo is between 0 and 1000 | 1.1 x
doIt( 9, 'x') # -> foo is an int | foo is between 3 and 17 | 9 x
如果您可以声明前置/后置条件,那么就可以减少很多模糊性的发生。
在最后这个例子中有几件事情需要注意。在上一个例子中,我们总是使用相同的 doIt() 名来定义通用函数 doIt() 的独特性。然而,这并不是这种命名模式的要求。每个特性都可以按照您所喜欢的方式进行命名,在适用时最好使用描述性名称。通用函数本身必须使用 decorator 进行命名来表示自己的独特性,并在最终会被分派的调用中使用。另外,专用函数在这个通用框架之外也可以使用。
例如,如果您喜欢,就可以自己调用 sayValues("blah","bloo");在这种情况中,其效果与调用 doIt("blah","bloo") 相同(但这只是因为这些参数都不满足前置条件和后置条件)。
为什么会出现这种问题?
通用函数的概念(尤其是断言分派函数的思想)最初可能有点难以理解。但是断言分派是对(狭窄)类型本身进行多分派的一个很好的扩展。
PEAK dispatch 包中最大的优点是可以对模块更精确而简明地进行模块化。在定义通用函数和一些独特性之后,您就可以自由添加其他独特性了,所有这些都不用对原来的代码进行任何修改(但愿经过了良好的测试)。对于大型的协作或为了简化那些为相关版本进行调整的应用程序来说,这个包显得尤其有用。
虽然在本文中并没有介绍,但是 Phillip J. Eby 已经考虑了很多工作来优化这个分派框架,因此您不需要担心这些有用的机制会显著地影响使用它们的程序的速度。您只需要自如地清理代码就可以了。
- ››深入理解JAR包
- ››深入分析Volatile的实现原理
- ››深入理解Flash Player的应用程序域(Application ...
- ››深入理解flash函数(AS2)
- ››深入理解Android消息处理系统——Looper、Handler...
- ››深入理解SET NAMES和mysql(i)_set_charset的区别
- ››深入理解Mysql字符集设置
- ››深入浅出实战攻防恶意PDF文档
- ››深入剖析防火墙策略的执行过程:ISA2006系列之六
- ››深入JavaScript与.NET Framework中的日期时间(3)...
- ››深入JavaScript与.NET Framework中的日期时间(2)...
- ››深入JavaScript与.NET Framework中的日期时间(1)...
更多精彩
赞助商链接