迭代器和生成器,装饰器小记

     可以被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)









posted @ 2020-06-22 20:06  xiaojianfir  阅读(168)  评论(0)    收藏  举报