精华内容
下载资源
问答
  • 迭代器

    千次阅读 2013-05-23 15:47:45
    迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器的部分或全部元素,每个迭代器对象代表容器的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都...

    迭代器

    编辑本段解释

    迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
    迭代器提供一些基本操作符:*、++、==、!=、=。这些操作和C/C++“操作array元素”时的指针接口一致。不同之处在于,迭代器是个所谓的智能指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型别都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义于内部。因此各种迭代器的接口相同,型号却不同。这直接导出了泛型程序设计的概念:所有操作行为都使用相同接口,虽然它们的型别不同。

    功能

    迭代器使开发人员能够在类或结构中支持foreach迭代,而不必整个实现IEnumerable或者IEnumerator接口。只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,将自动生成IEnumerable接口或者IEnumerator接口的Current,MoveNext和Dispose方法。

    特点

    1.迭代器是可以返回相同类型值的有序序列的一段代码;
    2.迭代器可用作方法、运算符或get访问器的代码体;
    3.迭代器代码使用yieldreturn语句依次返回每个元素,yield break将终止迭代;
    4.可以在类中实现多个迭代器,每个迭代器都必须像任何类成员一样有惟一的名称,并且可以在foreach语句中被客户端,代码调用如下所示:foreach(int x in SampleClass.Iterator2){};
    5.迭代器的返回类型必须为IEnumerable和IEnumerator中的任意一种;
    6.迭代器是产生值的有序序列的一个语句块,不同于有一个 或多个yield语句存在的常规语句块;
    7.迭代器不是一种成员,它只是实现函数成员的方式,理解这一点是很重要的,一个通过迭代器实现的成员,可以被其他可能或不可能通过迭代器实现的成员覆盖和重载
    8.迭代器块在C#语法中不是独特的元素,它们在几个方面受到限制,并且主要作用在函数成员声明的语义上,它们在语法上只是语句块而已;
    9.yield关键字用于指定返回的值。到达yieldreturn语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。 迭代器对集合类特别有用,它提供一种简单的方法来迭代不常用的数据结构(如二进制树)。

    简介

    迭代器是一种检查容器内元素并遍历元素的数据类型。

    编辑本段一个简单例子

    #include <iostream>
    using namespace std;
    class _iterator
    {
    private:
    char* p;
    public:
    _iterator(char* str):p(str){}
    char*& operator++()
    {
    p+=1; //跟 p++同价;
    return p;
    }
    };
    int main()
    {
    char* p="This is C++ program";
    _iterator it(p);
    cout<<"++之前:"<<p<<endl;
    char* p1=++it; //把地址向前加了一个char 型长度,然后给指针p1
    cout<<"++之后:"<<p1<<endl;
    return 0;
    }
    迭代器模式。Iterator对已集合类中的任何一个实现类,都可以返回这样一个Iterator对象。就和循环一样,好处是可以适用于任何一个类,而且实际上java对它进行了优化,比直接用index访问快一点(这一点没法考证,别人都这样说)。不过呢,有一点很好,就是用起来确实很好用,加上泛型就更好用啦。比如说这样一个例子ArrayList< String > arr = new ArrayList< String >();Iterator it = arr.iterator();迭代的时候可以这样while( it .hasNext() ){ //做一些处理,比如 System.out.print( it.next );}配合上泛型,一个好处是it.next()可以不用类型转换。以前用的时候是Object,还要自己转,我感觉,Iterator和泛型简直就是绝配哈。
    展开全文
  • 迭代器与相应类型推导在写作泛型函数或代码时,我们可能存在这样的需要:与参数相关的其它类型,比如一个迭代器的类型,在算法运用迭代器时,很可能会用到其也叫相应类型(associate type)。什么是相应类型? ...

    代码上传至

    https://github.com/gatieme/AderXCoding/tree/master/language/cpp/iterator_associate_type

    或者

    https://github.com/gatieme/STLSourceAnalysis/tree/master/stl-gatieme/3-iterator的3function_template*.cpp源代码

    迭代器与相应类型推导


    在写作泛型函数或代码时,我们可能存在这样的需要:与参数相关的其它类型,比如一个迭代器的值的类型,在算法中运用迭代器时,很可能会用到其也叫相应类型(associate type)。

    什么是相应类型?
    迭代器所指之物的类型就是其中一个。如果我们的算法中有必要声明一个变量,以”迭代器所指对象的类别”为型号。

    本文要向大家展示一个函数模板推导机制使用技法,这个在STL的迭代器和许多排序算法中广泛使用。

    考虑一个情况,我们在写一个泛型函数,它接受一对迭代器,要做的事就是对这一对迭代器之间的元素进行排序,其中将出现这幕:我需要对两个值进行交换。不知道大家有没有写过这样的代码,现在的问题是如何实现这两个值的交换?

    如:

    if(*itr > *(itr+1))
    {
        //交换两个迭代器指向的值
        //注意此时我们并不(*itr)的类型
    }

    很显然我们需要了解到迭代器所指向的具体类型,这该怎么好呢

    毕竟如果C++没有只支持sizeof(),并不支持typeof()

    有些人说了我们有RTT1机制中的typeid(),是的很好,但是那获取到的也只是类型名称name,而不是类型type,更不可能来做变量声明

    关于RTT1机制中的typeid(),请参见C++ typeid关键字详解

    解决方法一函数模版的参数推导机制


    解决的方法:利用函数模版(function template)的参数推导(argument deducation)机制。

    示例


    ///理解模板类型推导
    #include <iostream>
    
    template <class Iter, class T>
    void func_impl(Iter iter, T t)
    
    {
        T tmp;              //  这里解决了问题, T就是迭代器所指之物的类型, 本例为int
    
        /// ...  这里做原来func应该做的全部工作
    }
    
    
    
    
    template<class Iter>
    inline func(Iter iter)
    {
        func_impl(iter, *iter);
    }
    
    
    int main( )
    {
        int i;
        func(&i);
    }
    

    解析


    参数推导机制,以func()为对外接口,却把实际的操作全部置于func_impl()之中,由于func_impl()是一个函数模版(function template),一旦被调用,编译器会自动进行template的参数推导,于是导出类型T的问题,顺利得到了解决。

    问题


    但是迭代器相应类型不只是“迭代器所指对象的类型”一种而已

    根据经验,最常用的相应类型有5种,然而并非任何情况下任何一种都可利用函数模版的参数推导机制来取得。

    因此我们需要更一般的解法。

    解决方法二使用嵌套依赖类型(nested depended name)


    也称为Traits编程技法,是STL中广泛使用的技巧

    迭代器所指对象的类型,称为迭代器的value type,上述的参数类型推导技巧虽然可用于value type,却并不对所有的相应类型可用。

    前面的情况,通过隐藏了中间层,通过函数模版自己去推导参数类型,我们的接口也只是关心迭代器而不在意其指向的,但是如果我们的对外接口不能不了解到其相应类型的时候,这种方法就不适用了。

    比如如下情况,万一value type必须用于函数的返回值,就束手无策了。

    毕竟函数的“template参数推导机制”推而导之的只是参数,无法推导函数的回返值类型。

    我们需要其他方法,有什么好的方法呢,还记得之前提到的typename的以及嵌套依赖类型(nested depended name)么。

    那不就可以么,我们不妨一试

    参见 C++中typename和class在声明模板时的区别

    示例


    #include <iostream>
    template <class T>
    struct MyIter
    {
        MyIter(T *p = NULL)
        :m_ptr(p)
        {
            /// NOP...
        }
    
        T& operator*( ) const
        {
            return *m_ptr;
        }
    
    
    
        typedef T value_type;       //  内嵌类型声明{nested type}
        T   *m_ptr;
    };
    
    
    template <class Iter>
    typename Iter::value_type          ///  这一整行func的返回值类型
    func(Iter iter)
    {
        ///
        return *iter;
    }
    
    
    int main(void)
    {
        MyIter<int> ite(new int(8));
        std::cout <<func(ite) <<std::endl;
        return 0;
    }
    

    解析


    func()的返回值被定义为typename Iter::value_type

    内嵌类型被定义为 typedef T value_type

    由于T是一个template参数,在它被编译器具体化之前,编译器对T一无所知,换句话说,编译器此时并不知道MyIter<T>::value_type代表的是一个类型还是一个成员函数或者说是一个数据成员,

    而这个typename关键字的用意就在于告诉编译器这个是一个类型,如敝才能顺利通过编译。

    问题


    这样我们的问题似乎得到了解决,但是这里有一个隐晦的陷阱:并不是所有的迭代器都是类class type,比如有原生的指针就不是。如果不是class type,就无法为它定义内嵌类型。

    但是这显然不是我们做模版类所期待的,在STL(甚至于整个泛型思维)绝对接受原生的指针作为一种迭代器,所有我们上面的方法还不够,有没有什么方法可以让上述的一般化概念针对特定情况(比如原生的指针类型)做特殊化处理呢?

    特性萃取机器–偏序化实现支持原生类型


    那么这就是template partial specialization可以完成的

    模版特化问题


    如果class template拥有一个以上的template参数,那么可以针对其中某个(或者多个,但是不能全部)的参数进行特化工作。

    换句话说,我们可以在泛化设计中提供一个特化的版本。即通过将泛化版本中的某些template参数赋予明确的指定。

    /// 泛化的C接收任意类型
    template <typename T>
    class C             //  这个泛化版本允许接受T为任意类型
    {
        // NOP...
    };
    
    
    /// 特化的类C接收原生的指针作为对象
    template <typename T>
    class C<T*>             //  这个泛化版本适用于"T为原生指针的情况"
    {
        //  T为原生指针便是T为任何型别的一个更进一步的条件限制
        // NOP...
    };

    关于函数模版的特化问题,不是我们今天的重点,要了解详细信息,请参见
    C++模板的特化详解(函数模版特殊,类模版特化)

    通过针对任何template参数的模版,进行特化,得到一个限制了参数对象的特化版本。

    有了这个利器,我们就可以解决前述的”内嵌类型”未能解决的问题,先前的问题是,原生的指针并非class,因此无法为他们定义内嵌型别。

    现在我们可以通过对迭代器指针为参数的特化对象,来设计可以接收原生指针的特殊迭代器。

    万能的中间层

    因此我们设计出一个中间层,并添加一个value type内嵌对象

    //  泛化的iterator_traits对象
    template <typename Iter>
    struct iterator_traits
    {
        typedef typename I::value_type value_type;
    };
    

    这个所谓的traits迭代器说明,如果Iter定义有自己的value type,那么就通过这个traits的作用,萃取出来的value_type成员就是Iter::value_type。

    换句话说,如果I定义有自己的value type,那么先前的那个func就成为

    //  之前的func
    template <class Iter>
    typename Iter::value_type          ///  这一整行func的返回值类型
    func(Iter iter)
    {
        ///
        return *iter;
    }
    
    
    //  新的func
    template <class Iter>
    //typename Iter::value_type          ///  这一整行func的返回值类型
    typename iterator_traits<Iter>::value_type
    func(Iter iter)
    {
        ///
        return *iter;
    }

    特化中间层以支持原生指针


    增加iterator_traits这一中间层,现在我们为iterator_traits添加特化版本。

    // 特化的iterator_traits接收<T*>参数
    template<class T>
    struct iterator_traits<T *>
    {
        typedef T value_type;
    };

    通过这种方式,原生的指针比如int *虽然不是类对象class type,亦可通过traits取其value type。

    于是我们的迭代器支持原生的指针类型了。

    但是这样子够了么,请看下面的例子,

    当我们使用指向const常数对象的指针时,看看发生了什么

    iterator_traits<const int *>::value_type

    获得到的是一个const int,而不是int。很显然这个并不是我们所期望?

    比如我们利用这种方式来声明一个临时变量,使其类别与迭代器的value type相同,而现在,声明一个无法赋值(因const之故)的暂时变量,并没有什么卵用。

    这一切的一切,就只是因为我们获取到的迭代器的value type是一个pointer-to-const

    进一步特殊const


    // 特化的iterator_traits接收<const T*>参数, 萃取出一个T型
    template<class T>
    struct iterator_traits<const T *>   /
    {
        typedef T value_type;
    };

    现在OK了,不管是针对迭代器MyIterm,还是原生的指针int ,甚至是const int ,都可以通过traits取出正确的value type

    代码


    ///c++11 条款1:理解模板类型推导
    ///http://blog.csdn.net/coolmeme/article/details/43986163
    ///http://blog.csdn.net/shinehoo/article/details/5722362
    ///  STL源码剖析 PDF-119/534
    
    #include <iostream>
    #include <typeinfo>
    
    
    #include <iostream>
    template <class T>
    struct MyIter
    {
        MyIter(T *p = NULL)
        :m_ptr(p)
        {
            /// NOP...
        }
    
        T& operator*( ) const
        {
            return *m_ptr;
        }
    
    
    
        typedef T value_type;       //  内嵌型别声明{nested type}
        T   *m_ptr;
    };
    
    
    / 泛化的C接收任意类型
    //template <typename T>
    //class C             //  这个泛化版本允许接受T为任意类型
    //{
    //    // NOP...
    //};
    //
    //
    / 特化的类C接收原生的指针作为对象
    //template <typename T>
    //class C<T*>             //  这个泛化版本适用于"T为原生指针的情况"
    //{
    //    //  T为原生指针便是T为任何型别的一个更进一步的条件限制
    //    // NOP...
    //};
    
    
    //  泛化的iterator_traits对象
    template <typename Iter>
    struct iterator_traits
    {
        typedef typename Iter::value_type value_type;
    };
    
    // 特化的iterator_traits接收<T*>参数, 萃取出一个T类型
    template<class T>
    struct iterator_traits<T *>
    {
        typedef T value_type;
    };
    
    // 特化的iterator_traits接收<const T*>参数, 萃取出一个T型
    template<class T>
    struct iterator_traits<const T *>
    {
        typedef T value_type;
    };
    
    
    template <class Iter>
    //typename Iter::value_type          ///  这一整行func的返回值类型
    typename iterator_traits<Iter>::value_type
    func(Iter iter)
    {
        ///
        return *iter;
    }
    
    
    
    int main(void)
    {
    
        MyIter<int> ite(new int(8));
        std::cout <<func(ite) <<std::endl;
    
    
        std::cout <<typeid(iterator_traits< MyIter<int> >::value_type).name();
        std::cout <<typeid(iterator_traits<int *>::value_type).name();
        std::cout <<typeid(iterator_traits<const int *>::value_type).name();
    
    
        return 0;
    }
    

    最后通过traits这个特性萃取机角色,可以巧妙的萃取出各个迭代器的属性。

    STL中迭代器的设计


    这点我们可以在STL源码的找到对应的设计,参见 stl_iterator_base.h
    由于

    #ifdef __STL_USE_NAMESPACES
    template <class _Category, class _Tp, class _Distance = ptrdiff_t,
              class _Pointer = _Tp*, class _Reference = _Tp&>
    struct iterator {
      typedef _Category  iterator_category;
      typedef _Tp        value_type;
      typedef _Distance  difference_type;
      typedef _Pointer   pointer;
      typedef _Reference reference;
    };
    #endif /* __STL_USE_NAMESPACES */
    
    #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
    
    template <class _Iterator>
    struct iterator_traits {
      typedef typename _Iterator::iterator_category iterator_category;
      typedef typename _Iterator::value_type        value_type;
      typedef typename _Iterator::difference_type   difference_type;
      typedef typename _Iterator::pointer           pointer;
      typedef typename _Iterator::reference         reference;
    };
    
    template <class _Tp>
    struct iterator_traits<_Tp*> {
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef _Tp*                        pointer;
      typedef _Tp&                        reference;
    };
    
    template <class _Tp>
    struct iterator_traits<const _Tp*> {
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef const _Tp*                  pointer;
      typedef const _Tp&                  reference;
    };
    展开全文
  • 次读取reduce函数中迭代器的数据

    千次阅读 2016-05-13 16:30:20
    spark,hadoop交流群,QQ群号:521066396,欢迎加入共同学习,一起进步~第一次碰到读取reduce函数中迭代器的数据只能一次的问题。为了优化,在reduce函数,Iterable values只能被读取一次。查阅相关资料,如果要...

    spark,hadoop交流群,QQ群号:521066396,欢迎加入共同学习,一起进步~

    第一次碰到读取reduce函数中迭代器的数据只能取一次的问题。为了优化,在reduce函数中,Iterable values只能被读取一次。查阅相关资料,如果要反复使用,需要克隆或者新生成对象。举个简单例子:
    如果在reduce函数中读过values,

    for (Text value : values) {
        //do what you want
    }

    当reduce将数据填充到值迭代器的时候,应用了对象重用。这个特性对缓存机制有潜在影响。如果还想再使用values,那么需要克隆或保存新的对象。

    List<Text> lists = new ArrayList<Text>();
    Iterator<Text> iter = values.iterator();
    while (iter.hasNext()) {
        lists.add(iter.next());
    }

    下面是采用克隆的方式。

    //创建一个集合,存放
    ArrayList<Text> list = new ArrayList<Text>();
    for (Text value : values) {
        //克隆
        Text text = WritableUtils.clone(value,context.getConfiguration());
        list.add(text);
    }
    展开全文
  • 函数 islice() 返回一可以生成指定元素的迭代器,通过遍历并丢弃直到切片开始索引位置的所有元素,然后开始一个个的返回元素,并直到切片结束索引位置。 import itertools def count(n): while True: yield n...

    1. 迭代器切片

    迭代器和生成器不能使用标准的切片操作,因为它们的长度事先并不知道(并且也没有实现索引)。 函数 islice() 返回一个可以生成指定元素的迭代器,通过遍历并丢弃直到切片开始索引位置的所有元素,然后开始一个个的返回元素,并直到切片结束索引位置。

    import itertools
    def count(n):
        while True:
            yield n 
            n += 1
    
    c = count(0)
    # print( c[10:20] ) 
    # TypeError: 'generator' object is not subscriptable
    
    for num in itertools.islice(c, 10, 15):
        print(num)
    # >>> 10, 11, 12, 13, 14

    这里需要强调的一点是 islice() 会消耗掉传入的迭代器中的数据。 而迭代器是不可逆的。 所以如果需要之后再次访问这个迭代器的话,就得先将它里面的数据放入一个列表中了。

    2. 排列组合的迭代遍历

    如果我们想迭代遍历集合中元素的所有可能的排列或组合,可以用itertools模块提供两函数来解决这类问题。

    • itertools.permutations() , 接受集合并产生一个元组序列,每个元组由集合中所有元素的一个可能排列组成。 也就是说通过打乱集合中元素排列顺序生成一个元组。如果想得到指定长度的排列,可以传递长度参数permutation(items, length)。
    from itertools import permutations
    
    items = ['a', 'b', 'c']
    for sample in permutations(items):
        print( sample )
    # >>> ('a', 'b', 'c')
    #     ('a', 'c', 'b')
    #     ('b', 'a', 'c')
    #     ('b', 'c', 'a')
    #     ('c', 'a', 'b')
    #     ('c', 'b', 'a')
    • itertools.combinations() 得到输入集合中元素的所有的组合
    from itertools import combinations
    for sample in combinations(items, 3):
        print(sample)
    # >>> ('a', 'b', 'c')

    对于 combinations() ,元素的顺序已经不重要了。 也就是说,组合 ('a', 'b') 跟 ('b', 'a') 其实是一样的.

    3. 序列上索引值迭代 enumerate()

    如果我们想在迭代一个序列的同时跟踪正在被处理的元素索引时可以采用这种方法。这种情况在遍历文件时想在错误消息中使用行号定位时候非常有用。

    my_list = ['a', 'b', 'c']
    for idx, val in enumerate(my_list):
        print(idx, val)
    # >>> 0 a
    #     1 b
    #     2 c

    遍历文件消息时,可以直接用于发现文件消息发生错误所处的位置(行号):

    def parse_data(filename):
        with open(filename, 'rt') as f:
            for idx, line in enumerate(f,1): # from Line 1
                fields = line.split()
                try:
                    # cnt = int (fields[1])
                    pass
                except ValueError as e:
                    print('Line{}:Parse error: {}'.format(idx, e))
    
    parse_data('test.txt')

    4. 同时迭代多个序列 zip()

    如何同时迭代多个序列,每次分别从一个序列中取一个元素?zip()函数就是为了解决多个序列同时迭代而设计的。

    • zip() 最小迭代终止
    xpts = [1, 5, 4, 2, 10]
    ypts = [101, 78, 37, 15, 62, 99,56, 22]
    for x, y in zip(xpts, ypts):
        print(x,y)
    # >>> 1 101
    #     5 78
    #     4 37
    #     2 15
    #     10 62
    
    

    zip(a, b) 会生成一个可返回元组 (x, y) 的迭代器,其中x来自a,y来自b。 一旦其中某个序列到底结尾,迭代宣告结束。 因此迭代长度跟参数中最短序列长度一致

    • zip_longest() 最大迭代终止
    from itertools import zip_longest
    
    xpts = [1, 5, 4, 2, 10]
    ypts = [101, 78, 37, 15, 62, 99, 56, 22]
    for x, y in zip_longest(xpts, ypts):
        print(x,y)
    # >>> 1 101
    #     5 78
    #     4 37
    #     2 15
    #     10 62
    #    None 99
    #    None 56
    #    None 22

    zip() 函数对于同时处理两个、两个以上的序列非常有用。需要注意的一点是:zip() 会创建一个迭代器来作为结果返回。 如果需要将结对的值存储在列表中,要使用list() 函数

    xpts = [1, 5, 4, 2, 10]
    ypts = [101, 78, 37, 15, 62, 99, 56, 22]
    print(zip(xpts, ypts))
    # >>> <zip object at 0x0000000007505F88>
    print(list(zip(xpts, ypts)))
    # >>> [(1, 101), (5, 78), (4, 37), (2, 15), (10, 62)]

    5. 不同集合上元素的迭代

    如果我们想在多个对象执行相同的操作,但是这些对象在不同的容器中。在不失可读性的情况下如何避免写重复的循环?itertools.chain() 可以用来简化这个任务。 它接受可迭代对象列表作为输入,并返回一个迭代器,有效的屏蔽掉在多个容器中迭代细节。 

    from itertools import chain
    
    a = [1, 2]
    b = ['x', 'y', 'z']
    for x in chain(a, b):
        print(x)
    # >>> 1 2 x y z
        
    print(chain(a, b))
    # >>> <itertools.chain object at 0x0000000008B18978>
    
    print(list(chain(a,b)))
    # >>> [1, 2, 'x', 'y', 'z']

    itertools.chain() 接受一个或多个可迭代对象作为输入参数。 然后创建一个迭代器,依次连续的返回每个可迭代对象中的元素。 这种方式(chain(a,b))要比先将序列合并(a+b)再迭代要高效的多。a + b 操作会创建一个全新的序列并要求a和b的类型一致。 chian() 不会有这一步,所以如果输入序列非常大的时候会很省内存。 并且当可迭代对象类型不一样的时候 chain() 同样可以很好的工作。

    文章参考《python3-cookbook》

    展开全文
  • JAVA设计模式--迭代器模式

    万次阅读 多人点赞 2017-02-11 13:01:59
    目录 一、什么是迭代器模式 ...提供一种方法顺序访问一聚合(指一组对象的组合结构,如:Java的集合、数组等)对象各个元素,而又不需暴露该对象的内部表示。 迭代器模式的本质:控制访问...
  • C++STL各个迭代器详解

    千次阅读 2019-04-01 23:04:54
    1、自C++11起可以用range-based for循环来所有元素,但有时并不需要处理所有元素,此时可以使用迭代器。 std::vector<int> vec {1,2,3,4,5,6,7,8,9,10};...2、迭代器中用来表现容器的某个位置 oper...
  • Python的 生成器、迭代器

    万次阅读 2020-05-31 16:42:11
    上一次输出的结果为下一次输入的初始,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始 什么是迭代 访问集合元素的一种方式 可通过 for 循环遍历的对象 叫可迭代对象 数字类型 ...
  • python3 迭代器(自定义迭代器

    千次阅读 2018-09-13 11:28:41
    1.迭代器 1.什么是迭代器? 1.迭代器是用于迭代数据的 ... -迭代器通过__next__方法取得下一指向的 2.迭代器也称迭代对象,迭代对象指可以通过for .. in ..等语句将数据内容 显示出来的...
  • 迭代器与生成器的使用

    千次阅读 2017-12-23 21:56:38
    为什么要有迭代器可迭代的对象迭代器对象迭代器总结迭代器优缺点总结生成器什么是生成器生成器就是迭代器yield的功能yield为我们提供了一种自定义迭代器对象的方法yield与return的区别: 1、yield可以返回 ...
  • 详解生成器、迭代器

    千次阅读 2017-06-17 09:56:06
    何为迭代,何为可迭代对象,何为生成器,何为迭代器?  2.可迭代对象与迭代器之间的区别  3.生成器内部原理解析,for循环迭代内部原理解析  4.可迭代对象,迭代器,生成器,生成器函数之间关系 1.迭
  • 五、迭代器--迭代器类型详述

    千次阅读 2017-08-16 15:47:13
    五、迭代器标签(空格分隔): c++STL1. 迭代器及其特性 迭代器本身就是一种对象 迭代器不是通用指针,而是指向数组...输入:为程序需要数据源提供接口,数据源可以是容器,数据流等,输入迭代器只能序列读入数据
  • Python的内建函数,可迭代对象,迭代器

    千次阅读 多人点赞 2019-04-10 19:55:17
    Python的内建函数和可迭代对象,迭代器标识 id() #标识id 返回对象的唯一标识,CPython返回内存地址 hash() #哈希, 返回对象的哈希 len(s) -->返回一集合类型的元素数 range(start,stop[,...
  • Java 迭代器综述

    千次阅读 2016-12-06 15:40:27
    一般来说,我们只要实现一容器,就需要同时提供这容器的迭代器。使用迭代器的好处是:封装容器的内部实现细节,对于不同的集合,可以提供统一的遍历方式,简化客户端的访问和获取容器内数据。在此基础上,我们...
  • Python的可迭代对象、迭代器和生成器的异同点

    千次阅读 多人点赞 2019-01-16 18:12:01
    在Python学习之初比较容易混淆可迭代对象、迭代器和生成器。因此,做以总结以辨析其中关键的区别。以下仅为习后个人理解,如有偏差,还请指出! Talk is cheap,show me the picture! 解释之前,我们先来看一张...
  • STL Iterator 迭代器

    千次阅读 2016-05-21 16:07:52
    STL 迭代器学习 总结相关概念知识
  • c++iterator迭代器和vector容器

    千次阅读 2017-10-07 19:29:21
    vector是同一种类型的对象的集合,每对象都有一对应的整数索引。和string对象一样,标准库负责管理存储元素的相关内存。我们把vector称为容器,是因为它可以包含其他对象。一容器的所有对象都必须是同一种...
  • python迭代器 for循环

    千次阅读 2015-02-11 22:53:55
    3. 迭代器 3.1. 迭代器(Iterator)概述 迭代器是访问集合内元素的一种方式。...迭代器也不是线程安全的,在线程环境对可变集合使用迭代器是一危险的操作。但如果小心谨慎,或者干脆贯彻函数式思想坚持
  • JS迭代器和生成器

    千次阅读 2017-06-02 17:32:00
    迭代器iterator是一个object,这个object有一个next函数,该函数返回一个有value和done属性的object,其中value指向迭代序列的下个值。这样看来迭代器定义简直简单的感人T_T. 例如下列code function ...
  • python3迭代器与生成器

    千次阅读 2017-03-12 17:42:32
    迭代器(iterator) 生成器(generator) python3
  • 迭代器是一所谓的smart pointers。具有遍历复杂数据结构的能力,其下层运行机制决于所遍历的数据结构。因此,每一种容器都必须提供自己的迭代器。事实上,每一种容器都将迭代器以嵌套的方式定义与内部,因此各种...
  • C++迭代器 iterator详解

    千次阅读 2020-04-05 19:31:26
    迭代器是一变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器的某个元素,通过迭代器就可以读写它指向的元素。这一点上看,迭代器和指针类似。 迭代器按照定义方式分成以下四种。 正向迭代器...
  • 因此,在讲迭代器转换为列表时,需要给迭代器能够迭代的元素限定一范围,否则内存就会溢出。要想让迭代器停止迭代,需要抛出StopIteration异常即可。通过list函数可以直接将迭代器转换为列表。 [例...
  • 迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始,单纯的重复并不是迭代 ...
  • C++迭代器操作

    千次阅读 2019-03-09 10:54:35
    一、advance 头文件iterator template &lt;class InputIterator, class Distance&...通过n元素位置推进迭代器。 如果它是随机访问迭代器,则该函数仅使用一次operator +或operator-。 否则,该函数重复...
  • ②iterator object(迭代器): ③迭代器的应用场景 四.为什么要来到“生成器”? ①迭代器生成斐波那契数列 ②生成器生成斐波那契数列 ③应用情景 参考文献: 借用一位大佬的话:“yield” is your ...
  • C++STL为什么要使用迭代器

    千次阅读 2018-09-20 00:26:45
    原因: 1、通过迭代器访问容器,可以避免许多错误,同时...3、迭代器本身有很优点,可以弥补C++语言的不足,比如它的iterator_category,可以得到迭代器所指向的类别,这样可以根据不同的类别的特性,提供不同的...
  • 迭代器和生成器

    千次阅读 2020-04-25 14:16:50
    早安,世界,烦恼是每人不可少的生活小情调,快乐也是,每天睁开眼的那一刻,又便是新的出生,摒弃以流失的种种,珍惜现在每一刻,忘却还未到来的明天,活在当下,不以己悲,以的是生活带来的乐趣和指引。...
  • 迭代器快速失败异常问题

    千次阅读 2012-05-15 01:35:07
    当你用集合的迭代器进行迭代操作时 可以通过迭代器的方法增删集合里德元素这样是没问题的 ...当你 用hasNext进行判断 迭代器进行迭代时 可以用集合的remove 方法删除倒数第2元素不会报错 原因 假如集合的大...
  • C/C++迭代器使用详解

    万次阅读 多人点赞 2014-06-23 11:00:17
    迭代器是一种检查容器内元素并遍历元素的数据类型。
  • 迭代器、可迭代对象、生成器

    千次阅读 2018-01-03 19:37:35
    假如我们自己写了一数据类型,希望这数据类型里的东西也可以使用for被一出来,那我们就必须满足for的要求。这要求就叫做“协议”。 可以被迭代要满足的要求就叫做可迭代协议。*可迭代协议的定义...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 128,717
精华内容 51,486
关键字:

从迭代器中取多个值