引言
相信无论是谁,第一次接触Python,肯定会为她的优雅简洁感到震撼(她的性能咱先抛一边去),然而本人主要使用C和Java开发,Python虽然感觉很好,但是碍于一些环境因素,没机会去使用,况且语言只是一种工具,现在像Python这种高级动态语言又确实不少,掌握其本质思想才是关键,所以本文通过分析Java和Python的一些语法特性,用Java语言设计实现了Python语言中的强大而实用的生成器。本文只是使用Java的设计模式模仿Python的生成器,真正的生成器是由continuation实现的。
从range开始
玩过Python的都知道,在循环的时候都提倡使用如下风格的语法:
for item in IteratbleObj:
doSomething(item)
好在J2SE5后也引入了这种循环方式foreach,让Java增色不少,写起来更加方便舒服了:
for(elementType item : IterableObj)
doSomething(item);
但是,在初学Python的时候,肯定会碰到这个实用的内置函数:range()
在Python2里它的作用是通过指定范围和步长生成一个左闭右开的等差整数序列:
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1,10,2))
[1, 3, 5, 7, 9]
>>> list(range(1,10,-2))
[]
>>> list(range(1,-10,-2))
[1, -1, -3, -5, -7, -9]
>>> list(range(1,-10,2))
[]
>>> list(range(1,10,0))
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
list(range(1,10,0))
ValueError: range() arg 3 must not be zero
>>>
range()默认start为0,默认step为1,step为0则抛出异常。
如果指定范围是一个递增序列但是step为负数,或者指定范围是一个递减序列但step为正数,将返回长度为0的序列。
这个函数经常在Python中用来和for一起使用迭代下标:
for i in range(10):
print(i)
可以在Java中轻松实现range:
/**
* 仿Python range,生成一个整数等差序列(数组)
*
* @param from
* @param to
* @param step
* @return
*/
public static int[] range(int from, int to, int step) {
if(step == 0) //步长为0非法
throw new IllegalArgumentException(String.valueOf(step));
int[] sequence = null;
if(!(from<to ^ step>0)) { //递增序列则步长必须为正数,反之亦然
sequence = new int[(int) Math.ceil((to - from) * 1.0 / step)]; //预算长度
for (int i = 0, len = sequence.length; i < len; from += step)
sequence[i++] = from;
} else
sequence = new int[0];
return sequence;
}
/**
* 生成一个整数等差序列(数组), 默认步长为1
*
* @param from
* @param to
* @return
*/
public static int[] range(int from, int to) {
return range(from, to, 1);
}
/**
* 生成一个整数等差序列(数组),默认从0开始,步长为1
*
* @param to
* @return
*/
public static int[] range(int to) {
return range(0, to, 1);
}
这样子可以在Java中写出和Python一样的for语句:
for(int i : range(10)) //静态导入range方法
System.out.print(i+", ");
System