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

    * 递归 * 总结 ##迭代器

    可迭代对象(iteration)

    遵守可迭代对象的协议 具有__iter__()方法

    print(dict.__iter__({‘i’:1}))
    

    除去整型和布尔值剩下现已知都是
    迭代器(iterator): 遵守迭代器的协议 具有__iter__()方法和__next__()方法
    创建一个迭代器 == 可迭代对象.iter()
    使用迭代器 == 迭代器.next()

    迭代器:不能回退,惰性机制,一次性的

    for循环的机制 两种方式

    1.
    lst = [1,2,3,4,5]
    count = 0
    l = lst.__iter__()
    while count < len(lst):
        print(l.__next__())
        count += 1
    2.
    lst = [1,2,3,4,5,67,7]
    l = lst.__iter__()
    while True:
    try:   # 异常捕获
      print(l.__next__())
    except StopIteration:
      break
    s = '123'.__iter__()
    s1 = s.__iter__()
    print(s1.__next__())
    print(s.__next__())
    

    怎么查看是迭代器还是可迭代对象:

    from collections import Iterator,Iterable
    print(isinstance([1,2,3],Iterable))   # 查看是否是可迭代的
    print(isinstance('查看的内容',Iterator))   # 查看是否是迭代器
    

    加上__.iter__()就是迭代器

    生成器

    定义

    函数体中存在yield就是生成器,函数+()就产生 生成器
    _next__ 和 yield 要一一对应, 最后的一个yield下边能写就是不运行

    def foo():
        print(1)
        n = yield 2
        print(n)
        print(3)
        yield 4
    g = foo()
    print(g) #<generator object foo at 0x0000026218165AF0>
    print(g.__next__())
    print(g.send(66))
    

    结果:1 2 66 3 4
    send() 发送 send() == next + 传值
    send()传递给上一个yield的
    最后的一个 yield 下边的可以写代码,但是执行不到
    第一次启动这个生成器的时候 生成器.next 或 生成器.send(None)

    生成器的好处

    节省空间
    可以for去执行这个生成器直接打印i就行,for的本身就是一直的__next__
    yield from 调用的时候只能使用__next__()啊

    推导式

    1)列表推导 a=[结果 for I in 可迭代对象]

    li = [i for i in range(10) if i>4] 
    

    2)字典dic={k:v for k,v in 可迭代}

    dic={'a':'b','c':'d'}
    d={k:c for k,c in dic.items()}
        print(d)
    

    3)集合s=set{结果 for I in 可迭代对象}

    lst=['a','c']
    lst1=['b','d']
    d={lst[i]:lst1[i] for i in range(2)}
        print(d)
    

    4)生成器s=(结果 for I in 可迭代对象) 长得像元祖

    l=(i for i in range(100))
    for i in range(10):
        print(l.__next__())
    

    装饰器

    1.本质就是闭包
    开放封闭原则
    扩展开发,修改源代码封闭,不能修改调用方式
    在不改源代码的基础上添加功能
    @装饰器的名字 在被装饰的函数正上方  独占一行
    @语法糖 被装饰的函数名 = 装饰器的名字(被装饰的函数名)

    2.装饰器作用:

    在不改变函数调用方式的基础上添加一些功能

    3.functools.wraps的作用

    保留原有函数的名称(消除装饰器带来的副作用)

    简单写一个装饰器

    import time
    def timer(func):
        def inner(*args,**kwargs):
            start = time.time()
            re = func(*args,**kwargs)
            print(time.time()-start)
            return re
        return inner
      
    @timer     #==> func1 = timer(func1)
    def func1(a,b):
        print('in func1')
    
    @timer
    def func2(a):
        print('in func2  and get a:%s'%(a))    #n func2  and get a:cccc 
        return 'func2 over'
    
    func1('aaa','bbbb')   #in func1
    print(func2('cccc'))   #i  func2 over
    

    有参装饰器

    内置函数

    all()可迭代对象中都为真才是真
    Any()可迭代对象中有一个为真就是真
    callable判断是否可调用
    print(pow(2,3)) 求幂
    print(pow(2,3,3)) 求幂后再取余
    print(round(3.332324,3)) #四舍五入 第一个参数是浮点数  第二参数的要保留的小数位

    1.lambda匿名函数

    语法:lambda 参数:返回值
    定义:lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。

    lambda函数有什么好处?

    lambda函数比较轻便,即用即仍;
    匿名函数,一般用来给filter,map这样的函数式编程服务;
    作为回调函数,传递给某些应用,比如消息处理

    匿名函数没有名字,怎么查看 函数.name
    匿名函数的返回值只能是一个,不能是多个
    匿名函数可不可以写到一行

    print((lambda x,y:x+y)(3,6))  
    

    print((lambda x:x)()) 调用的时候要传参

    def func(n):
        return n**n
    print(func(4))
      等同于下:
    f = lambda x: x**x
    print(f(4))
    

    写上end=' '和不写end是换行,end=''是两个连在一起

    print('bjk','hjb',sep='   |') #sep默认是空格
    print('mk','jjnk',end='')
    

    repr显示数据原生
    例:1)和函数组合使用
     定义一个列表,然后根据一元素的长度排序
    lst = ['天龙八部','西游记','红楼梦','三国演义']
    def func(s):
        return len(s)
    print(sorted(lst,key=func))
     结果:
    ['西游记', '红楼梦', '天龙八部', '三国演义']
    2)和lambda组合使用:
    lst = ['天龙八部','西游记','红楼梦','三国演义']
    print(sorted(lst,key=lambda s:len(s)))

    2.sorted()

    sorted :内置函数 排序
    语法:sorted(iterable,key=None,reverse=False)
    sorted('可迭代对象',key='函数名(函数名里写排序规则),reverse=True的时候是降序')

    print(sorted(lst))
    
    3. filter()过滤

    函数可以是匿名,也可以是定义好的,得有判断条件  
    语法: filter(function,iterable)

    dic=[{'a':'d','s':15},{'d':'k','s':1}]
    print(list(filter(lambda x:x['s']>5,dic)))
    
    4.map() 映射函数,累加

    语法: map(function,iterable)
    一个列表中每个元素的平方

    print(list(map(lambda x:x**2,lst)))
    
    5.zip() 拉链

    将对象中对应的元素打包成一个个元祖,返回的是对个,如果有三个可迭代对象,就按照最短的进行输出#4.

    lst1 = [1,2,3]
    lst2 = ['a','b','c','d']
    lst3 = (11,12,13,14,15)
    


    for i in zip(lst1,lst2,lst3):
        print(i)

    结果:
    (1, 'a', 11)
    (2, 'b', 12)
    (3, 'c', 13) 

    6.enumerate(lst,10) #枚举

    将可迭代对象放到里边,默认数字是0开始,自己指定开始的数字

    li = ['x','a','sd']
    for i,e in enumerate(li,10):
        print(i,e)
    结果
    """
    10 x
    11 a
    12 sd
    
    """
    
    7.reduce 累计算 从python3中引入

    语法:reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行
    第一次的时候 x是1 y是2 x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了
    第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了
    第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了

    from functools import reduce
    lst=[1,5,3]
    print(reduce(lambda x,y:x*y,lst))
    

    递归:

    递 函数调用
    归 函数的返回值
    1)1.自己不断调用自己本身 -- 1,死递归
    2.有明确的终止条件 -- 1,2 才是有效递归
    2) 默认深度是1000 实际测试998
    修改深度 import sys

    import sys
    sys.setrecursionlimit('修改的数量')
    

    递归的应用: 文件查看 创建文件,删除文件

    总结

    迭代器:
    具有 iternext 的就是迭代器
    生成器一定是一个迭代器,迭代器不一定是生成器
    具有 iternext,send 的就是生成器

    区别

    1.生成器和迭代器的区别:
    迭代器必须是定义了__iter方法和__next方法的对象.它每次调用时会返回自身的下一个元素,比传统方式节省内存;
    生成器是一次生成一个值的特殊类型的函数, 调用该函数将返回一个可用于生成连续某值的生成器.

  • 相关阅读:
    LintCode-174.删除链表中倒数第n个节点
    LintCode-165.合并两个排序链表
    LintCode-371.用递归打印数字
    LintCode-140.快速幂
    LintCode-373.奇偶分割数组
    NOI 2015 品酒大会 (后缀数组+并查集)
    NOI 2016 优秀的拆分 (后缀数组+差分)
    POJ 2774 Long Long Message (后缀数组+二分)
    BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
    POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
  • 原文地址:https://www.cnblogs.com/xm-179987734/p/12296188.html
Copyright © 2011-2022 走看看