迭代器和生成器,装饰器小记
可以被for循环的对象都是可迭代对象,这句话不正确,(字符串,列表,元组,字典,集合,文件) 都不是可迭代对象,为什么,whye
因为可迭代对象首先要遵循可迭代协议,可迭代协议中必须有一个next方法 就是说可迭代对象必须有next方法,来遍寻所有元素。但是上面这些类型都没有这个方法
for 循环其实就是先把上面的类型变成可迭代对象,再把超出可迭代对象的报警处理掉 ,这样就能把对象里面的元素全部取出来。但是while循环也可以依依取出元素,要for循环干嘛。while循环无法取出无序的字典,集合,文件。
for 循环的目的其实就是统一了可迭代类型变成可迭代对象,实现依依取元素的目的。
a = 'huangjian'
b = a.__iter__() #先把对象变成可迭代对象(iter方法),再一次使用next方法取值。
print(type(b))
print(b.__next__())
print(b.__next__()) #也可以用系统自带函数next(b)
#超出就会报警,但是for循环变我们过滤掉报警并且停止循环
由以上的说明可知,for循环是你用一次next取一次值,如果值有地方存放,就会存放在内存中,如果没有内存就会销毁。这样的好处对取数据比较大的对象里面的元素比较好,不会一次读完所有数据存着再去取里面的元素(有可能数据太大内存被撑爆),而是按你next的次数,取得值存在与否看你是不是存着
迭代器就是可迭代对象
生成器
生成器就是可迭代对象,他直接是可迭代对象,不像其余的类型(字典什么的还要iter方法来实现自己是迭代器)。
有哪些类型生成器
1.函数生成器 把return 换成yield 则变成了生成器。每次执行函数yield 返回其值,暂停函数。再次执行就会继续执行下面的函数程序
import time
def consumer(name):
print("%s 准备吃包子了!" %name)
while True:
baozi = yield
print("包子[%s]来了,被[%s]吃了" %(baozi,name))
实现简单的单线程多线任务:
def producer(name):
c = consumer("A")
c2 = consumer("B")
c.__next__()
c2.__next__()
print("老子要开始做包子了")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2send(i) #注 这里的c.send(i) 和c2send(i)可以理解为2个不同的解释器
#其实这里就是利用生成器的yield的特性,调用生成器,执行
#到yield则会跳出,再次调用则会回到生成器执行,这样就能
#实现在以一个函数中调用生成器,返回回来,继续执行函数
#。这样就能本身函数和生成器来回切换,实现一些功能。 此处是baozi = yield
send传值到生成器c,和c2替换yield
producer("huangjian")
2.生成器表达式和列表解析
三元运算
myname = 'huangjian'
aa = print("ture") if 'huangjian' == myname else '错误' #三元运算 其实就是函数三步操作的简单化 必须符合函数逻辑格式 这个aa的值没有任何意义,只是记录了一个函数的过程 必须三元,多少都不行
列表解析
a = [i for i in range(5) ] #列表解析 里面是三元运算得到i值,在外面套一层列表就会制动加入列表 可以少一元,但是不能多一元
变成生成器表达式
c = (i for i in range(5)) #用()把类表解析变成了可迭代对象,就是生成器。这个只占用很小的内存空间
其实就是把列表解析变成了一个生成器 ,列表解析又用到了三元表达式
生成器只能遍历一次所有元素,再遍历就会是空值
装饰器
本质是一种函数, (装饰其他函数)就是为其他函数添加附加功能的 在py中decorator 就表示装饰器 或者叫语法糖
原则:
1: 不能修改被装饰的函数的源代码
2: 不能修改被装饰的函数的调用方式
自己总结:
装饰器就是一种可以增加函数运算过程的东西,但是不能更改源代码函数。就相当于四驱车上加一些其他的什么龙头凤尾,但是不能再车本上修改而达到什么目的
实现装饰器只是储备:
1.函数即"变量" 2.高阶函数 3,嵌套函数
高阶函数+嵌套函数=》 装饰器
import time 简单装饰器,mytime装饰器装饰test函数,
def mytime(x):
def haha(i):
start_time = time.time() 函数是执行流程是test()执行,因为有@mytime装饰器,就去执行装饰器了,mytine函数把test函数名变成参数x执行函数,return了haha 因为是装饰器,所以执行haha函数(注意,如果不是装饰器,要执行return后面的函数
x(i) 不能是函数名,而是执行函数操作加(),如果是自身就是尾递归了),haha函数里面的参数是test()函数里面的参数,执行haha函数,函数里面有x(i) x是test函数, 而i 是test函数的参数 所以就完成在装饰器中执行原函
end_time = time.time() 数了,且执行了别的函数功能。
len_time = start_time - end_time
print(len_time)
return haha
@mytime
def test(x):
num = 0
time.sleep(1)
for i in range(x):
num+=i
print(num)
return num
test(10)
在装饰器上加参数的话,其实就是多一个参数,根据这个参数做出判断,执行装饰器里面哪个函数,实现一个装饰器可以装饰多个函数并且增加不同的功能
a = "黄健"
b = 123
def auth(auth_type):
def deco(x): #带入的参数是auth_tpye
def local(): #带入的输入函数
if auth_type == "local":
account = input("请输入你的账户:")
password = int( input("请输入你的密码:"))
if a == account and b == password:
x()
else:
print("账号密码错误")
elif auth_type == "ldap":
x()
print("ldap验证方式不会。。。。。")
else:
x()
return local
return deco
def index():
print("welcome to index page")
@auth(auth_type = "local")
def home():
print("welcome to home page")
return "huangjian"
@auth(auth_type = "ldap")
def bbs():
print("welcome to bbs page")
home()
解压序列
a,b,c = [1,2,3] 后面可循环的对象 ,一一对应
print(a)
a,*_,b =[1,2,3,4,5,6,7,8,9] *号表示所有值,_表示*存的变量名,把中间元素全部存在_中
print(a)
print(b)
a = 1
b = 2
a,b = [b,a]
print(a)

浙公网安备 33010602011771号