zoukankan      html  css  js  c++  java
  • Python基础(4)

    迭代器、生成器、装饰器

    一、装饰器

    1、函数对象:可以把函数名(不带括号)当成变量去用,关联的值是该函数的内存地址

    2、闭包函数=作用域+函数嵌套+函数对象

      核心点:内部函数传参的关系查找是以定义阶段为准

    3、什么是闭包函数?

      闭包是一个嵌套函数,内层函数调用了外层函数作用域的变量,外层函数返回值为内层函数名

      实质:为函数wrapper传参的一种方式

      “函数指的是该函数是内嵌函数

      “函数指的是该函数包含对其外层函数作用域名字的引用

    def outer():
        x=1
        def wrapper():
            print(x)
        return wrapper
    f=outer()  #为什么要返回函数名wrapper:打破内嵌函数wapper只能在outer函数内部调用的规则,使得重回全局调用
    f()

    4、闭包函数解决的痛点:当wrapper函数体需要传参,又不能直接通过形参传入时,闭包就可以解决此问题

    5、什么是装饰器?

      定义一个函数(类),在不改变被装饰函数源代码及调用方式的情况下为其增加功能。

    import time
    def target(x,y): time.sleep(3) print("my name is {} ,age is {}".format(x,y)) return "ok"
    #需求:不改变target函数源代码和调用方式的情况下统计target函数的运行时间 import time
    def outer(func): #func体现闭包的功能,给wrapper函数体传入需要的参数func,为了不改变target源码 def wrapper(*args,**kwargs): #*args,**kwargs被装饰函数需要的参数 start=time.time() res=func(*args,**kwargs) end=time.time() print(end-start) return res return wrapper #target=outer(target) #为了不改变target调用方式 #偷梁换柱:将target函数名指向的内存地址换成了wrapper @outer def target(x,y): time.sleep(3) print("my name is {} ,age is {}".format(x,y)) return "ok" target("lennie",28)#没动源码,也没改变调用方式

    6、无参装饰器模板

    def outer(func):
        def wrapper(*args,**kwargs):
            
            res=func(*args,**kwargs)
            
            return res
    return wrapper

    7、有参装饰器

      在outer函数外再套一层函数outer2,将outer函数体需要的参数,通过outer2形参传入,即成了有参装饰器。

    def decorator(x):
    def outer(func):
    def wrapper(*args, **kwargs):
    res = func(*args, **kwargs)
    print(x)
    return res

    return wrapper

    return outer

     

    二、迭代器

    1、迭代:每一次对过程的重复称为一次迭代,而与单纯的重复不同,每一次迭代得到的结果会作为下一次迭代的初始值

    #重复
    while True:
        msg = input('>>: ').strip()
        print(msg)
        
    #迭代    
    goods=['mac','lenovo','acer','dell','sony']
    index=0
    while index < len(goods):
        print(goods[index])
        index+=1

    2、可迭代对象:内置有__iter__()方法的对象都是可迭代对象,字符串、列表、元组、字典、集合、打开的文件都是可迭代对象,可以直接被for循环遍历通过obj.__iter__()或者iter(obj)可以返回一个迭代器对象iterator

    3、迭代器:迭代器即用来迭代取值的工具Python提供的一种统一的、不依赖于索引的迭代取值方式,只要存在多个,无论序列类型还是非序列类型都可以按照迭代器的方式取值。

    4、迭代器对象:内置有__next__()方法的对象,可以通过iterator.__next__()或者next(iterator)取出出迭代器中的下一个值,可以直接被for循环遍历

    >>> s={1,2,3} # 可迭代对象s
    >>> i=iter(s)  # 本质就是在调用s.__iter__(),返回s的迭代器对象i,
    >>> next(i) # 本质就是在调用i.__next__()
    1
    >>> next(i)
    2
    >>> next(i)
    3
    >>> next(i)  #抛出StopIteration的异常,代表无值可取,迭代结束
    

      

    三、生成器

    1、什么是生成器/生成器对象?

      生成器函数(含yield关键字)的返回值为生成器对象,内置有__iter__()和__next__()方法,所以生成器本身就是一个迭代器可以直接被for循环遍历

    >>> def my_range(start,stop,step=1):
    ...     print('start...')
    ...     while start < stop:
    ...         yield start
    ...         start+=step
    ...     print('end...')
    ... 
    >>> g=my_range(0,3)
    >>> g
    <generator object my_range at 0x104105678> #直接调用不执行函数体
    >>> g.__iter__
    <method-wrapper '__iter__' of generator object at 0x1037d2af0>
    >>> g.__next__
    <method-wrapper '__next__' of generator object at 0x1037d2af0>
    >>> next(g) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
    start...
    0
    >>> next(g) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
    1
    >>> next(g) # 周而复始...
    2
    >>> next(g) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
    end...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

    2、什么是生成器函数: 

    1. 含有yield语句的函数
    2. 调用生成器函数将返回一个生成器对象,不执行函数体
    3. yield翻译为产生生成”,返回多个对象用yield(迭代),返回一个对象用return

    (1) 调用生成器函数会自动创建迭代器对象。

    (2) 调用迭代器对象的__next__()方法时才执行生成器函数。

    (3) 每次执行到yield语句时返回数据,暂时离开。

    (4) 待下次调用__next__()方法时继续从离开处继续执行。

    3、作用:在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。

    4、生成器表达式

      创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:

    >>> [x*x for x in range(3)]
    [0, 1, 4]
    >>> g=(x*x for x in range(3))
    >>> g
    <generator object <genexpr> at 0x101be0ba0>
    >>> next(g)    #对比列表生成式,生成器表达式的优点自然是节省内存(一次只产生一个值在内存中)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g) #抛出异常StopIteration
    

    四、lambda表达式及内置高阶函数

    1、lambda表达式

    • 定义:是一种匿名函数(方法)
    • 作用:作为参数(实参)传递时语法简洁,优雅,代码可读性强。随时创建和销毁,减少程序耦合度。
    • 语法

    1.定义:

      变量 = lambda 形参: 方法体

    2.调用:

      变量(实参)

    • 说明:

    -- 形参没有可以不填

    -- 方法体只能有一条语句,且不支持赋值语句

    2、内置生成器函数

    1. enumerate(可迭代对象):遍历可迭代对象时,可以将索引与元素组合为一个元组。
    2. zip(可迭代对象1, 可迭代对象2….):将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。
    3. map(函数,可迭代对象):映射,使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象(生成器对象)。
    4. filter(函数,可迭代对象):过滤,根据条件筛选可迭代对象中的元素,返回值为新可迭代对象(生成器对象)。
    >>:a=[1,2,3]
    >>:b=[4,5,6]
    >>:ge=enumerate(a) #返回一个生成器,每个元素为一个元组(index,value)
    >>:ge
    <enumerate object at 0x000000000357C240>
    >>:list(ge)
    [(0, 1), (1, 2), (2, 3)]
    >>:next(ge)
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    StopIteration
    >>:ge=zip(a,b)  #返回一个生成器,每个元素为一个元组(a[index],b[index])
    >>:ge
    <zip object at 0x0000000003435308>
    >>:next(ge)
    (1, 4)
    >>:list(ge)
    [(2, 5), (3, 6)]
    >>:ge=map(lambda x : x**2 , a)  #让a中每个元素平方,返回一个生成器
    >>:ge
    <map object at 0x000000000356AC50>
    >>:next(ge)
    1
    >>:next(ge)
    4
    >>:next(ge)
    9
    >>:next(ge)
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    StopIteration
    >>:ge=filter(lambda x :x%2==0,b)  #筛选b中满足条件的元素,返回一个生成器
    >>:ge
    >>:<filter object at 0x000000000356A828>
    >>:list(ge)
    [4, 6]

     

     
  • 相关阅读:
    【Rust】多种错误类型
    【Rust】Result别名
    【Rust】Option然后
    【Rust】可选和错误
    【Rust】Result问号
    【Rust】Option转换
    【Rust】Option展开
    【Rust】Result结果
    【Rust】Result提前返回
    jQuery过滤 安静点
  • 原文地址:https://www.cnblogs.com/lennie-luo/p/12886088.html
Copyright © 2011-2022 走看看