zoukankan      html  css  js  c++  java
  • day04 迭代器&生成器&装饰器

    目录  

    1.迭代器

    2.生成器

    3.推导式

    4.匿名函数

    5.内置函数

    6.递归

    7.闭包

    8.装饰器

    一.迭代器

    特点:

        1. 省内存
    2. 只能向前. 不能反复
    3. 惰性机制
    让不同的数据类型有相同的遍历方式

    迭代器取值方法:
    lst = [1,2,3,4]
    lst1 = lst.__iter__()
    print(next(lst1))
    print(lst1.__next__())

    判断是不是可迭代对象和迭代器
    from collections import Iterator,Iterable
    lst = [1,2,3,4]
    print(isinstance(lst,Iterable)) 可迭代对象
    print(isinstance(lst,Iterator)) 迭代器
    用while循环打印迭代器并异常捕捉
    lst = ["黑色星期天","bad feel","滚吧","那就这样吧"]
    lst1 = lst.__iter__()
    while True:
    try:
    s = lst1.__next__()
    print(s)
    except StopIteration:
    break

    dir() 查看我们数据类型可以执行的操作

    二.生成器
    生成器本质上也是一个迭代器,特点也是节省空间。通过yield来定义
    def func():
    yield
    生成器函数 -> 执行的时候. 不会立即把函数全部执行完. 创建一个生成器返回给你

    省内存
    __next__() 可以拿到数据
    send() 可以拿到数据, 可以给生成器传递消息 send会给上一个yield传递参数。

    普通打印例子:
    def order():
    lst = []
    for i in range(1000):
    lst.append("衣服" + str(i))
    return lst
    lst = order()
    print(lst) ps:当数据量多大内存容易出问题

    生成器例子:
    def order():
    lst = []
    for i in range(100):
    yield "衣服" + str(i)

    gen = order()
    print(gen.__next__()) ps:要一个值打印一下next即可,惰性机制的特点。

    send应用
    def func():
    print("韭菜盒子")
    s1 = yield 1
    print("s1=", s1)
    print("沙琪玛")
    s2 = yield 2
    print("s2=", s2)
    print("盒饭")
    s3 = yield 3
    print("s3=", s3)
    print("混沌")
    s4 = yield 4
    gen = func()
    print(gen.__next__()) # send可以给上一个yield位置传值
    ret1 = gen.send("周润发")
    ret2 = gen.send("周杰伦")
    ret3 = gen.send("周笔畅")
    print("===============")
    print(ret1)
    print(ret2)
    print(ret3) ps:send是给上一个yield传值,不能给最后一个yield传值,否则会报错

    三.推导式

    列表推导式:
    [结果 for循环 if语句]
    例子1:lst = ["python周末班%s" % i for i in range(1, 27) if i%2==0 ]
    print(lst)
    例子2:把姓张的人检索出来, 放在一个新列表里 startswith
    lst = ["欧阳娜娜", "张崔猛", "欧阳难过", "张亚无照", "胡一飞", "胡怎么飞", "张炸辉"]
    print([name for name in lst if name.startswith("张")])

    例子3:使用列表推导式得到 [1, 4, 9, 16, 25, 36]
    print([i*i for i in range(1,7)])
    例4在[3,6,9]的基础上推到出[[1,2,3], [4,5,6],[7,8,9]]
    print([[i-2,i-1,i] for i in [3,6,9]])
    字典推导式:
    {key:value for if}
    例1:通过列表推导成字典
    lst = ["张三丰", "张无忌", "张翠山"]
    print({i:lst[i] for i in range(len(lst))})
    集合推导式
    {key for if}
    print({i for i in range(10)})
        没有元组推导式!!!!!!!

    生成器表达式:
    (结果 for if)
    gen = (i for i in range(10))
    print(gen)
    for i in gen:
    print(i)

    四.匿名函数

    匿名函数语法:

      匿名函:lambda 参数: 返回值   配合内置函数一起使用 不能写太多

          func = lambda x:x*10

      print(func(10))

    例1:给函数传递一个参数,返回字符串的长度
    lambda args: len(args)

    五.内置函数

       repr() 字符串表示形式

       zip() 拉链函数

       sorted() 排序

          例子1:

    lst = ["高进", "波多野结衣", "苍老师", "仓木麻衣", "红狗"]
    s = sorted(lst,key=lambda s: len(s))
    print(s) ps:首先,打开这个可迭代对象. 然后获取到每一项数据. 把每一项数据传递给函数,根据函数返回的数据进行排序.

    例2:按照年龄大小排序
    lst = [{"id":1, "name":'alex', "age":18},
    {"id":2, "name":'wusir', "age":16},
    {"id":3, "name":'taibai', "age":17}]
    def func(d):
    return d["age"]
    s = sorted(lst,key=func,reverse=True)
    print(s)

    filter()帅选函数
    例1:筛选出大于20的数字
    st = [18, 22, 66, 35, 1, 48]
    f = filter(lambda n:n>20,st)
    for item in f:
    print(item) ps:返回迭代器, 把可迭代对象中的每一项数据交给前面的函数. 由函数决定该数据是否保留

    例2:打印大于或者等于18岁的成年人
    lst = [{"id":1, "name":'alex', "age":18},
    {"id":2, "name":'wusir', "age":16},
    {"id":3, "name":'taibai', "age":17}]

    s = filter(lambda n:n["age"]>=18,lst)
    for i in s:
    print(i)

    map() 会根据提供的函数对指定序列做映射
    lst = [2,5,3,2,4]
    m = map(lambda n:n*n, lst)
    for i in m:
    print(i) ps:python2 里面返回来的是列表,python3返回的是迭代器

    六.递归

        特点:实际上就是函数自己调自己,永远不可能超过1000层

        递归死循环

    i = 0
    def func():
    global i
    i +=i
    print("哈哈" ,i)
    func()
    func()

    传统的查找方法需要一个个对比很消耗资源
    lst = [12,24,53,67,108,267]
    n = 798
    for i in range(len(lst)):
    if lst[i] == n:
    print("I found it")
    else:
    print("didn't find it")
    递归用法
    def binarySearch(lst, n, left, right):
    if left <=right: # 判断是否已经查找完毕
    mid = (left+right)//2 # 计算中间
    if n > lst[mid]: # 数据比中间大
    left = mid + 1 # 做边界拉倒右边
    # 进入递归
    return binarySearch(lst, n, left, right)
    elif n < lst[mid]:
    right = mid - 1
    return binarySearch(lst, n, left, right)
    else:
    print("找到了")
    return mid
    else:
    print("没找到")
    return -1

    lst = [12,24,53,67,108,267]
    n = 108
    ret = binarySearch(lst, n, 0, len(lst)-1)
    print(ret)
    二分法,一个最简单的算法,用于查找某个数字
    n = 108
    lst = [12,24,53,67,108,267]
    left = 0
    right = len(lst) - 1 # 右边界
    while left <= right:
    mid = (left + right)//2
    if n > lst[mid]:
    left = mid+1
    elif n < lst[mid]:
    right = mid-1
    else:
    print("找到了")
    print(mid)
    break
    else:
    print("没有") ps:两头掐尾取中间。

    七.闭包

    作用:在内层函数中使用外层函数的变量

         1.保护变量

         2.让一个变量常驻内存

    定义:

    def outer():
    a = 10
    def inner():
    print(a)
    return inner
    outer = outer()
    outer()
    查看函数是不是闭包:
    def outer():
    a = 10
    def inner():
    print(a)
    return inner
    fn = outer()
    ret = fn()
    print(fn.__closure__)

    八.装饰器

    简洁版语法

    def func(fn):
    def inner():
    print("hahaha")
    fn()
    print("make a go")
    return inner

    @func
    def func1():
    print("我要离开地球表面")
    func1()

    精版
    def func(fn):
    def inner(*args,**kwargs):
    print("hahaha")
    ret = fn(*args,**kwargs)
    print("make a go")
    return ret
    return inner

    @func
    def func1(*args,**kwargs):
    print("我要离开地球表面")
    return "流光幸运刀"
    ret = func1("我要流光幸运刀")
    print(ret)

    ps:上面的装饰器当用户查看自己的函数时就能看出来就闭包。可以通过如下方法来掩饰
    from functools import wraps
    def waiguai(fn):
    @wraps(fn )
    def inner(*args,**kwargs):
    print("开外挂")
    ret = fn(*args,**kwargs)
    print("结束外挂")
    return ret
    return inner

    @waiguai
    def dnf(username,password):
    print("starting game")

    @waiguai
    def king(qq):
    print("王者")

    dnf1 = dnf("ivy","wang")
    print(dnf1)
    king("1327285005")
    print(king.__name__)
    给装饰器传递参数
    例子1:给装饰器传递一个值如果是True问金老板否则直接直接fn()
    主要实现原理是先执行@后面的函数然后在执行@,相当于分成两部分来实现。
    def outer(flag):
    def decoration(fn):
    def inner(*args,**kwargs):
    if flag:
    print("问问金老板去哪儿好")
    ret = fn(*args,**kwargs)
    print("金老板骗人的")
    else:
    ret = fn(*args, **kwargs)
    return ret
    return inner
    return decoration

    @outer(True)
    def dating():
    print("约帅哥。。。")
    dating()

    print("--------华丽丽的分割线------------")
    @outer(False)
    def travel():
    print("想想去哪儿。。。")
    travel()

    例子2,日志打印,重要的日志放在一指定的文件下面,不重要的放在默认路径下。
    import time

    def outer(filename="default.log"):
    def decoration(fn):
    def inner(*args,**kwargs):
    print("打印访问日志" )
    with open(filename,mode="a",encoding="utf-8") as f:
    f.write("在%s 访问了%s " % (time.strftime("%Y-%m-%d %H:%M:%S"),fn.__name__))
    ret = fn(*args,**kwargs)
    return fn
    return inner
    return decoration

    @outer("func1.log")
    def func1():
    print("Hello everyong I am func1")
    func1()

    @outer()
    def func2():
    print("Hello everyone I am func2")
    func2()
    ps: func1的日志打印到func1.log里面,func2的日志打印到default.log 里面,主要基于装饰器传参定义默认参数来实现的。

    多个装饰器装饰一个函数
    def decoration1(fn):
    def inner():
    print("before decoration1")
    fn()
    print("after decoration1")
    return inner

    def decoration2(fn):
    def inner():
    print("before decoration2")
    fn()
    print("after decoration2")
    return inner

    def decoration3(fn):
    def inner():
    print("before decoration3")
    fn()
    print("after decoration3")
    return inner

    @decoration1
    @decoration2
    @decoration3
    def func():
    print("hello I am the real funcation")
    func()

    打印结果

    由此可见多个装饰器装饰一个函数的原理,是一层层来实现的,最开始执行的是离函数最近的那个开始的。

    
    


    We are down, but not beaten. tested but not defeated.
  • 相关阅读:
    盛最多水的容器
    寻找2个有序数组的中位数
    从链表中删除总和值为0的连续节点
    链表中的下一个更大节点
    链表的中间节点
    循环有序链表的插入
    设计链表
    链表组件
    扁平化多级双向链表
    将二叉搜索数转化为排序的双向链表
  • 原文地址:https://www.cnblogs.com/guniang/p/10747394.html
Copyright © 2011-2022 走看看