zoukankan      html  css  js  c++  java
  • 四:迭代器生成器

    一:迭代器

    暂时不涉及到自定义迭代器,涉及到了再补,暂时知道for循环的原理就可以了.

    1有__iter__就是可迭代的,也叫可迭代协议

    2双下方法:c语言写好了的内置方法,可以用不止一种的方式调用

    3迭代取值的工具
    4可迭代对象执行__iter__得到的返回值就是迭代器.
    5可以把它看作数据流,只能前进不能后退,迭代到头了就会从内存消失
    6如果还有__next__方法,那么就是迭代器了,光有__next__就什么都不是
    7迭代器的另一个好处是节省内存,不会一次全在内存中生成,而是随着循环每次生成一个
    8只关心当前数据,和下一个数据的位置,其他数据没有在内存当中
    9迭代器一定是可迭代的
    10很少自己写迭代器,都是用for去循环可迭代对象,当到头没有数据报StopIteration异常,for循环完美的处理了这个异常.
    11.for循环的本质就是通过__iter__拿到迭代器,然后不断调用__next__获取数值,直到报异常并处理掉
    迭代器更多的是从已经存在的数据结构中获取值,就算没有索引也可以不断获取后面的数据,迭代器知道这些就可以了.
    迭代器几乎不会自己定义
    class Test:
        pass
    test = Test()
    for i in test:
        print(i)
    #TypeError: 'Test' object is not iterable
    for遍历不可迭代对象报错
    class Test:
        def __iter__(self):
            return self
    
    test = Test()
    for i in test:
        print(i)
    #TypeError: iter() returned non-iterator of type 'Test'
    for遍历可迭代对象,但不是迭代器报错
    class MyStudents:
        """
        自定义一个迭代器对象
        """
        stu_list = []
    
        def __init__(self, *args):
            names = args
            self.position = 0
            for name in names:
                self.stu_list.append(name)
        
        #对象本身就是迭代器,返回自身
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.position < len(self.stu_list):
                item = self.stu_list[self.position]
                self.position+=1
                return item
            else:
                raise StopIteration()
    
        def __str__(self):
            return self.stu_list.__str__()
    
        def add_student(self,stu_name):
            self.stu_list.append(stu_name)
    
    stus = MyStudents("张三","李四")
    stus.add_student("王五")
    stus.add_student("赵六")
    print(stus)
    for i in stus:
        print(i)
    自定义迭代器

    二:生成器本质是迭代器

    优点:不会一下子在内存中生成全部数据,调用一次__next__才生成一个数据
    生成器保存的是生成数据的逻辑,而非具体数据,调用一次生成一次数据
    生成器更多的是不断的根据外界条件来生成不同的值到内存中
    1生成器表达式:相同的生成数据的逻辑,后面说
    2生成器函数:含有yield的函数就是生成器函数,且根据不同的条件生成不同的数据
    1 def gen_test():
    2     for i in range(20):
    3         yield "test%s" % i
    简单生成器

    生成器函数调用了只会生成一个generator对象,不会执行里面的代码

    只有next(g)才会执行到第一个yield结束,并将值返回

    正好for循环就可以不断的调用next()

    三:表达式

    列表推导式:一次性生成全部数据

    li=[i**2 for i in range(10)]
    print(li)
    View Code

    for遍历每个元素,按照开头的规则生成每个元素,for的简写形式

    多层嵌套
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    #先for的外面的大列表,然后for里面的小列表
    #推导式的缺点是无法打断点,debug
    ret = [li for name in names for li in name if li.count("e")>=2]
    print(ret)
    View Code

    生成器表达式:不会全部数据一次性生成到内存中

    只把列表生成式外层中括号换成小括号即可

    字典推导式:原理还是for循环遍历的是key

    合并大小写对应的value值,将k统一成小写
    mcase2 = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    ret2 = {k.lower():mcase2.get(k.lower(),0)+mcase2.get(k.upper(),0) for k in mcase2}
    print(ret2)
    View Code

    集合推导式

    集合推倒式,和列表推到式就差一个{},多了去重的功能
    squared = {x**2 for x in [1, -1, 2]}
    print(squared)
    View Code
    看十遍不如自己写一遍!巩固基础,纵横开拓!
  • 相关阅读:
    Android官方架构组件介绍之ViewModel
    Android官方架构组件介绍之LiveData
    Android官方架构组件介绍之LifeCycle
    Android N 通知概览及example
    Project和Task
    hello gradle
    写出gradle风格的groovy代码
    Groovy中的面向对象
    tcp_tw_recycle和tcp_timestamps的一些知识(转)
    Xtrabackup 热备
  • 原文地址:https://www.cnblogs.com/gyxpy/p/11559613.html
Copyright © 2011-2022 走看看