迭代器的设计

迭代器的设计
对于一个编程语言来说,定制各种需要的数据结构是一项重要的能力,如果定制的手段非常精简,将会获得极大的开发效率提升,而构建的手段针对当前计算机底层很贴合,则可以有机会获得非常高的性能。
对于定制数据结构来说,最基础的一项操作就是,遍历所有内容,因为有了遍历,基本上就有了“读”的功能。
大家都知道,不同的数据结构无论是外在形态还是内部结构都相差甚远,有什么办法能提供一个统一的接口对内部所有数据进行便利呢?这就是所谓“迭代器”。
以C++为例,遍历一个vector:
#include  < iostream >
#include 
< vector >

int  main( int  argc,  char   * argv[])
{
    std::vector
< int >  a  =  { 1 2 3 };
    
for  (std::vector < int > ::iterator iter  =  a.begin(); iter  !=  a.end();  ++ iter)
    {
        std::cout 
<<   * iter  <<  std::endl;
    }
    
return   0 ;
}


我们可以看到,它定义了一个新类型,叫std::vector<int>::iterator,这么个类型就是迭代器类型。从直觉上看他就是给访问数据提供个类似指针的接口而已,实际上这个迭代器变量还有另一个重要功能,就是“保存状态”,有了这个状态,才能知道下一次迭代能得到什么结果。
后来C++11标准出来后在语法方面进行了加强,淡化了保存状态这么个过程,写出的代码显得更加简洁:
#include  < iostream >
#include 
< vector >

int  main( int  argc,  char   * argv[])
{
    std::vector
< int >  a  =  { 1 2 3 };
    
for  (auto iter : a)
    {
        std::cout 
<<  iter  <<  std::endl;
    }
    
return   0 ;
}

当然底层该有的操作是不会少的。

有了“保存状态”这个概念,实现编程语言的时候,就可以快速排除掉一些不靠谱的方案。
比如,不要迭代器而把状态保存在数据结构内部行不行?当然不行,考虑以下代码:
#include  < iostream >
#include 
< vector >

int  main( int  argc,  char   * argv[])
{
    std::vector
< int >  a  =  { 1 2 3 };
    
for  (std::vector < int > ::iterator iter  =  a.begin(); iter  !=  a.end();  ++ iter)
    {
        std::cout 
<<   * iter  <<   " " ;
        
for  (std::vector < int > ::iterator iter2  =  a.begin(); iter2  !=  a.end();  ++ iter2)
        {
            std::cout 
<<   * iter2  <<   "   " ;
        }
        std::cout 
<<  std::endl;
    }
    
return   0 ;
}

我们就知道,访问状态有时候是需要保存多份的,而对于引用类型的对象来说,状态要想在内部保存多份会更加复杂,还不如用显式的状态保存。
直接修改数据结构内部呢?比如用类似car和cdr循环赋值的方式进行遍历。这一样行不通,如果复制保存的引用类型真实数据,则代价太大,看不出引用类型的好处,而直接修改则会破坏数据本身,而数据可能之后还要使用。

以下Python作为例子如何创建一个可迭代的,Range对象:
class  Range:
    
def   __init__ (self, low, high):
        self.cur 
=  low
        self.high 
=  high
        
    
def   __iter__ (self):
        
return  self

    
def  next(self):
        
if  self.cur  >=  self.high:
            
raise  StopIteration
        
else :
            v 
=  self.cur
            self.cur 
+=   1
            
return  v

for  item  in  Range( 1 3 ):
    
print  item

创建对象的时候,执行了初始化方法和__iter__方法,在迭代的过程中则执行了和next方法,并且以StopIteration异常作为迭代结束的标志。

你可能感兴趣的:(迭代器的设计)