装饰器
-
装饰器的作用
- 装饰器的本质:一个闭包函数 (高阶函数+嵌套函数)
- 装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
-
闭包原理
def wraper(func): b = '我是b' # 闭包中inner中的b变量先从inner中获取值,没有则从wraper中获取一层层往上找 def inner(a): print(a,b) print('before') ret = func(a) print('after') return ret return inner @wraper def show_list(b): print('show_list') show_list('我是a')
-
装饰器执行流程
迭代器
-
迭代和可迭代协议
- 可以被for循环的都是可迭代的
- 字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的
证明:
from collections import Iterable l = [1,2,3,4] t = (1,2,3,4) d = {1:2,3:4} s = {1,2,3,4} print(isinstance(l,Iterable)) print(isinstance(t,Iterable)) print(isinstance(d,Iterable)) print(isinstance(s,Iterable))
结合我们使用for循环取值的现象,再从字面上理解一下,其实迭代就是我们刚刚说的,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代。
-
可迭代协议
从结果分析原因,能被for循环的就是“可迭代的”,但是for怎么知道谁是可迭代的呢?
假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。
**可以被迭代要满足的要求就叫做可迭代协议。**可迭代协议的定义非常简单,就是内部实现了__iter__方法。
扫描二维码关注公众号,回复: 11348341 查看本文章接下来我们就来验证一下:
可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法.
-
迭代协议
''' dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合, 然后取差集。 ''' #print(dir([1,2].__iter__())) #print(dir([1,2])) print(set(dir([1,2].__iter__()))-set(dir([1,2]))) 结果: {'__length_hint__', '__next__', '__setstate__'}
生成器
-
什么是生成器
我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
Python中提供的生成器:
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
迭代器生成器总结
可迭代对象:
拥有__iter__方法
特点:惰性运算
例如:range(),str,list,tuple,dict,set
迭代器Iterator:
拥有__iter__方法和__next__方法
例如:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o
生成器Generator:
本质:迭代器,所以拥有__iter__方法和__next__方法
特点:惰性运算,开发者自定义
迭代器和生成器
-迭代器
-可迭代协议--含有iter方法的都可以迭代的
-迭代器协议--含有next和iter的都是迭代器
特点:
-节省内存空间
-方便逐个取值,一个迭代器只能取一次
-生成器
所有的生成器都是迭代器
-含有yield 关键字的函数都是生成器函数
-生成器函数特点:
-调用之后函数内的代码不执行,返回生成器
-每从生成器中取一个值就会执行一段代码,遇见yield就停止
如何从生成器中取值?
-for : 如果没有break会一直取完
-next : 每次只取一次
-send: 不能用在一第一个,取下一个值的时候给上一个位置传一个新的值
- 数据类型强制转换:会一次性把所有的数据都读到内存中
生成器表达式:
(条件成立想放在生成器中的值 for i in 可迭代的 if 条件)