zoukankan      html  css  js  c++  java
  • 什么是容器和可迭代的对象(及生成器和迭代器)

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    #Author:qika
    
    
    '''
    一. 容器
    容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,
    可以用in, not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中
    (也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有:
    list, deque...
    set, frozensets(不可变集合)...
    dict, defaultdict, OrderedDict, Counter...
    tuple, namedtuple...
    str
    容器的概念就像一个盒子,可以往里面装东西.当它可以用来询问某个元素是否包含在其中时,
    那么这个对象就可以认为是一个容器,比如 list,set,tuples都是容器对象:
    
    
    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 (1, 2, 3)      # tuples
    assert 4 not in (1, 2, 3)
    
    询问某元素是否在dict中用dict的中key:
    
    d = {1: 'foo', 2: 'bar', 3: 'qux'}
    assert 1 in d
    assert 'foo' not in d  # 'foo' 不是dict中的元素
    询问某substring是否在string中:
    s = 'foobar'
    assert 'b' in s
    assert 'x' not in s
    assert 'foo' in s
    尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,
    而是可迭代对象赋予了容器这种能力,当然并不是所有的容器都是可迭代的,
    比如:Bloom filter,虽然Bloom filter可以用来检测某个元素是否包含在容器中,
    但是并不能从容器中获取其中的每一个值,因为Bloom filter压根就没把元素存储在容器中,
    而是通过一个散列函数映射成一个值保存在数组中。
    二. 可迭代对象(iterable)
    大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的。
    __iter__方法会返回迭代器(iterator)本身,例如:
    
    lst = [1,2,3]
    lst.__iter__()
    <listiterator object at 0x7f97c549aa50>
    Python提供一些语句和关键字用于访问可迭代对象的元素,比如for循环、列表解析、逻辑操作符等。
    
    判断一个对象是否是可迭代对象:
    
    from collections import Iterable  # 只导入Iterable方法
    isinstance('abc', Iterable)
    >>True
    isinstance(1, Iterable)
    >>False
    isinstance([], Iterable)
    >>True
    
    这里的isinstance()函数用于判断对象类型。
    可迭代对象一般都用for循环遍历元素,也就是能用for循环的对象都可称为可迭代对象。
    例如,遍历列表:
    
    lst = [1, 2, 3]
    for i in lst:
         print i
    
    '''
    
    
    
    #列表推导式
    # a = [x for x in range(10)]
    # b = [x**2 for x in range(10)]
    # print(a)
    # print(b)
    
    
    
    #生成器
    #可以理解为一种数据类型,自动实现迭代器协议
    #生成器创建:2种方式
    #第一种:(x for x in range(10))
    #第二种:yield
    
    
    '''
    #第一种方式:
    a = (x for x in range(10))
    print(a)#会打印<generator object <genexpr> at 0x0000000001DE2E60>,即生成器对象
    a1=a.__next__()  #通过内置的方法__next__()进行获取值
    print(a1)#打印值。但是始终都是默认获取的值是:0
    
    #因此,如果想要迭代获取范围内所有的值,都是通过next()来获取
    next(a)#获取第一次,获取的值为1
    next(a)#值为2
    #我临时插入做点其他的事情
    print(“我临时做其他的事情”)
    next(a)#值为3--->>
    这就是生成器的作用,虽然中途插入做了其他事情,但是我后面还是可以接着继续使用生成器函数
    
    
    
    #第二种方式:
    def test():
         print("one")
         yield 1    #yield 等同于  return 1
         print("two")
         yield 2   #yield 等同于  return 2
    
    t = test()
    print(t)#<generator object test at 0x0000000002132EB8>  会打印出这是个生成器对象
    #获取值,该怎么做?
    print(next(t))#打印一次,默认获取第一个值:one,1
    print(next(t))#打印第二次,获取值:two,2
    #另:如果像上面那样仅仅使用next(t)不加print,那么就只会执行函数内的内容,而不会管yield
    #此时就不会管print出yield的内容(所以yield就如同函数的return)
    # next(t)#获取第一次,值:one
    # next(t)#获取第二次,值:two
    
    #总结:-----------------------------------
    #在调用生成器的过程中,
    # 每次遇到yield时函数会暂停并保存打印出当前所有的运行信息并返回yield的值。
    #并在下一次执行next()方法时又继续运行后面的
    '''
    
    
    
    #send()方法
    '''
    def test():
         print("one")
    
         count=yield 1
         print(count)
    
         print("two")
         yield 2
    
    t = test()
    
    #注意!!!使用send()传值时,需要有“变量”接收
    t.send(None)#使用send时,第一次传值只能使用None,如同next(t)
    # print(t)
    t.send("aaa")
    '''
    
    
    
    
    
    ############################################
    ##############################################
    
    #迭代器


    #定义: #生成器都是迭代器(而迭代器不一定是生成器 ) #python中的内部工具(如for循环,sum,min,max函数等)基于迭代器协议访问对象。 #作用: # 1、省内存,如果使用列表,计算值时会一次获取所有值,那么就会占用更多的内存。 # 而迭代器则是一个接一个计算,只能向前,不能反复 # 2、使代码更通用、更简单。 # 3、惰性机制 #如何判断是不是迭代器? #需满足两个条件:1、有iter方法。2、有next方法 #实例: #迭代器的对象内部定义了一个__iter__()方法 l=[1,2,3,4,5,6] d=iter(l) #即相等于 l.__iter__() print(next(d))#迭代打印l列表内的值:1 print(next(d))#迭代打印l列表内的值:2 print(next(d))#迭代打印l列表内的值:3 #--->>从上可见,在“满足有iter方法时,有next方法存在”时,就是一个迭代器对象了!!! #-->>那么如何通过for循环来遍历一个迭代器对象??? # 用while循环模拟for循环机制 li=[1,2,3,4,5,6] diedai_l = li.__iter__() while True: try: print(diedai_l.__next__()) except StopIteration: print("迭代完毕,循环终止") break """ for循环时: 1调用可迭代对象的iter方法并返回一个迭代器对象 2不断调用迭代器对象的next方法 3处理stopiteration这个报错信息(因为超出边界了,超出了范围,会自动停止) """ #最后,如何通过代码判断是否为迭代器对象呢? #--->>通过isinstance()方法来判断 from collections import Iterator print(isinstance(1,list))#会打印出False,因为1不是列表,即:可迭代对象 li=[1,2,3,4,5,6] print(isinstance(li,list))#判断li列表,是否为list可迭代对象-->>结果会打印出true
  • 相关阅读:
    51 nod 1181 质数中的质数(质数筛法)
    Just oj 2018 C语言程序设计竞赛(高级组)F:Star(结构体排序+最小生成树)
    欧拉函数+费马小定理拓展
    ZOJ 3785 What day is that day?(数论:费马小定理)
    Just oj 2018 C语言程序设计竞赛(高级组)H: CBT?
    树链剖分(入门学习)
    bitset用法
    链式前向星
    Nearest Common Ancestors(LCA板子)
    LCA(最近公共祖先)
  • 原文地址:https://www.cnblogs.com/QiKa/p/14127143.html
Copyright © 2011-2022 走看看