Python三大器

迭代器、生成器、装饰器python

1、装饰器算法

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

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

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

3、什么是闭包函数?工具

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

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

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

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

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形参传入,即成了有参装饰器。

 

2、迭代器

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提供的一种统一的、不依赖于索引的迭代取值方式,只要存在多个,不管序列类型仍是非序列类型均可以按照迭代器的方式取值。

四、迭代器对象:内置有__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的异常,表明无值可取,迭代结束

  

2、生成器

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

  生成器函数(含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

二、什么是生成器函数: 

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

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

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

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

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

三、做用:在循环过程当中,按照某种算法推算数据,没必要建立容器存储完整的结果,从而节省内存空间。数据量越大,优点越明显。

四、生成器表达式

  建立一个生成器对象有两种方式,一种是调用带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
相关文章
相关标签/搜索