zoukankan      html  css  js  c++  java
  • Python:迭代器

    在使用Python的过程中,很容易混淆如下几个关联的概念:

    • 容器(container)
    • 可迭代对象(Iterable)
    • 迭代器(Iterator)
    • 生成器(generator)
    • 生成器表达式
    • {list, set, dict} 解析式

    1.容器(container)

    容器是用来储存元素的一种数据结构,它支持隶属测试,容器将所有数据保存在内存中,在Python中典型的容器有:

    • list, deque, ...
    • set,frozesets,...
    • dict, defaultdict, OrderedDict, Counter, ...
    • tuple, namedtuple, ...
    • str

    通过判断一个对象是否包含某个元素来确定它是否为一个容器

    >>> assert 1 in [1,2,3]       # lists
    >>> assert 4 not in [1,2,3]
    >>> assert 1 in {1,2,3}       # sets
    >>> assert 4 not in {1,2,3} 
    >>> assert 1 in (12,3)        # tuples
    >>> assert 4 not in (1,2,3)

    字典容器通过检查是否包含某个键来进行判断

    >>> d = {1:"foo", 2:"bar", 3:"qux"}
    >>> assert 1 in d
    >>> assert 4 in d
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError
    >>> assert "foo" in d
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError

    字符串通过检查是否包含某个子 串来判断

    >>> s="foo"
    >>> assert "f" in s
    >>> assert "b" in s
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError

    2.可迭代对象

    如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。

     很多容器都是可迭代对象,此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。但凡是可以返回一个 迭代器 的对象都可称之为可迭代对象,听起来可能有点困惑,没关系,可迭代对象与迭代器有一个非常重要的区别。

    >>> x=[1,2,3]
    >>> y=iter(x)
    >>> z=iter(x)
    >>> next(y)
    1
    >>> next(y)
    2
    >>> next(z)
    1
    >>> type(x)
    <class 'list'>
    >>> type(y)
    <class 'list_iterator'>

     x 是一个可迭代对象,可迭代对象和容器一样是一种通俗的叫法,并不是指某种具体的数据类型,list是可迭代对象,dict是可迭代对象,set也是可迭代对象。 y 和 z 是两个独立的迭代器,迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。迭代器有一种具体的迭代器类型,比如 list_iterator , set_iterator 。可迭代对象实现了 __iter__ 和 __next__ 方法(python2中是 next 方法,python3是 __next__ 方法),这两个方法对应内置函数 iter() 和 next() 。 __iter__ 方法返回可迭代对象本身,这使得他既是一个可迭代对象同时也是一个迭代器。

    3.一些迭代工具

    3.1并行迭代

    >>> names=['greg','greg1','greg2']
    >>> ages=[18,12,13]
    >>> for i in range(len(names)):
        print(names[i]+' is '+str(ages[i]))
    
        
    greg2 is 13
    greg2 is 13
    greg2 is 13
    >>> for n,a in zip(names,ages):
        print(names[i]+' is '+str(ages[i]))
    
        
    greg2 is 13
    greg2 is 13
    greg2 is 13

    3.2 编号迭代

    list1 = ["", "", "一个", "测试"]
    for index, item in enumerate(list1):
        print(index, item)
    
    0 这
    12 一个
    3 测试

    3.2 翻转和排序迭代

    >>> sorted([2,6,3,1,5])
    [1, 2, 3, 5, 6]
    >>> sorted('Hello,world!')
    ['!', ',', 'H', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
    >>> list(reversed('Hello,world!'))
    ['!', 'd', 'l', 'r', 'o', 'w', ',', 'o', 'l', 'l', 'e', 'H']
    >>> ''.join(reversed('Hello,world!'))
    '!dlrow,olleH'

    4.迭代器(iterator)

    它是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__() (python2中实现 next() )方法的对象都是迭代器,至于它是如何实现的这并不重要。

    #迭代器,1,有iter方法。2,有next方法
    # 可以使用isinstance()判断一个对象是否是Iterable对象:
    l=[1,2,3,4]
    d=iter(l)
    print(d) #<list_iterator object at 0x000002C34B71C160>
    # list,tuple,dict,string:iterable
    print(next(d))
    print(next(d))
    print(next(d))
    print(next(d))
    
    # for循环内部三件事:1,调用可迭代对象iter方法,返回迭代器对象
    # 2,不断调用迭代器对象的next方法
    # 3,处理StopIteration,遇到退出
    # for i in [1,2,3,4]:
    #     iter([1,2,3,4])
    
    from collections import Iterator,Iterable
    print(isinstance(2,list))#False
    l=[1,2,3,4]
    d=iter(l)
    print(d)
    print(isinstance(l,list))
    print(isinstance(l,Iterable))
    print(isinstance({}, Iterable))
    print(isinstance('abc', Iterable))
    print(isinstance((x for x in range(10)), Iterable))
    print(isinstance(100, Iterable))#False
    
    # 小结
    # 凡是可作用于for循环的对象都是Iterable类型;
    # 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
    # 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
    # Python的for循环本质上就是通过不断调用next()函数实现的,例如:
    
    
    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    while True:# 循环:
        try:# 获得下一个值:
            x = next(it)
        except StopIteration:# 遇到StopIteration就退出循环
            break

    可以使用迭代器来解决复用可占空间的问题

    class Fab(object):
        def __init__(self, max):
            self.max = max
            self.n, self.a, self.b = 0, 0, 1
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.n < self.max:
                r = self.b
                self.a, self.b = self.b, self.a + self.b
                self.n = self.n + 1
                return r
            raise StopIteration()
    
    for key in Fab(5):
        print(key)
        
    # 1
    # 1
    # 2
    # 3
    # 5

    Fab既是一个可迭代对象(因为它实现了 __iter__ 方法),又是一个迭代器(因为实现了 __next__ 方法)。实例变量 self .a 和 self.b 用户维护迭代器内部的状态。每次调用 next() 方法的时候做两件事:

    1. 为下一次调用 next() 方法修改状态
    2. 为当前这次调用生成返回结果

    迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

    5.从迭代器得到序列

     list构造方法显式将迭代器转化为列表

    class TestIterator:
        value=0
        def __next__(self):
            self.value +=1
            if self.value>10:
                raise StopIteration
            return self.value
        def __iter__(self):
            return self
    
    ti=TestIterator()
    print(list(ti))
    #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 相关阅读:
    分块的一些题(入门)
    HH的项链
    2019 CCPC-Wannafly Winter Camp Div2 Day1
    2019 CCPC-Wannafly Winter Camp Div2 Day7
    HDU-5672 String(尺取)
    POJ-3104 Drying(二分
    Codeforces
    Java把内存划分为4个部分 1. 代码区 1、栈区 3、堆区 4、静态区域
    二:java语法基础:
    一:java概述:
  • 原文地址:https://www.cnblogs.com/ningxin18/p/7820231.html
Copyright © 2011-2022 走看看