ll1123

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

迭代器、生成器、装饰器

一、装饰器

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]

 

 

 
posted on 2020-05-14 01:34  Lennie-L  阅读(82)  评论(0编辑  收藏  举报