python的重重之器(生成器、迭代器、装饰器)

Deadly 提交于 2020-03-06 02:55:34

一、装饰器

1、定义:本质是函数,装饰其他函数就是为其他函数添加附件功能。

2、原则:

  a.不能修改被装饰的函数的源代码;

  b.不能修改被装饰的函数的调用方式;

 实例:

  #!/usr/bin/env python  # -*- coding:utf-8 -*-  #Author:ye  import time  #装饰器  def time_cha(func):#func等于test      time_start = time.time()      func()#此时func()相当于test()      time.sleep(2)      time_stop = time.time()      print("the time cha is :%s" % (time_stop - time_start))  #主函数  def test():      print("*")      time.sleep(1)      print("*")      time.sleep(1)      print("in the test")  #单独调用主函数  test()  #将装饰器套用在主函数上  time_cha(test)#此方式改变了主函数的调用方式

3、实现装饰器的知识储备:

  a.函数即“变量”

  b.高阶函数

    b1.把一个函数名当做实参传递给另外一个函数(在不修改被装饰函数的前提下,增加其功能)

      实例:      

        def test1():#此函数时源代码            print("in the test1")        def test2(func):#此函数时装饰器            print("in the test2")            print(func)#打印test1的内存地址            func()#这里相当于test1()        test1()        test2(test1)#将test1这个函数名作为实参传递给test2,这样实现了高阶函数

    b2.返回值中包含函数名(不改变函数(源代码)的调用方式)

      实例:

        def test1():#源代码            print("in the test1")        def test2(func):#装饰器            print("in the test2")            func()            return test1#通过return,把函数名作为返回值        test1 = test2(test1)#此处是test1函数名的内存地址        test1()#执行test1函数

  c.嵌套函数

    def test1():#第一层函数      print("in the test1")      def test2():#第二层函数        print("in the test2")      test2()#第一层函数执行时,调用第二层函数    test1()#执行第一层函数

4、装饰器的案例分析:

 案例背景:首先定义两个模块,欧美专区和河南专区,两个专区的使用前提是需要登录。

      步骤一:首先实现两个专区的免登录访问;

      步骤二:定义登录模块,然后以登录模块做为装饰器,装饰在欧美专区和河南专区上

      步骤三:当调用到两个专区模块时,再进行登录验证,不能调用之前就进行验证(此处涉及到了嵌套函数的使用) 

      status = False            #初始化登录状态,false表示未登录,true表示已登录      def login(func):           #定义登录模块(装饰器函数)          def inner():            #定义嵌套函数              _uername = "zhangye"    #定义用户数据              global status        #将函数内变量全局化              if status ==False:     #根据状态判断是否需要登录                  username = input("请输入用户名:")                  if username == _uername:                      print("welcome...")                      status = True   #登录成功后,将默认状态由false转化为true              if status == True:                  print(func)                  func()          return inner           #未调用时,不进行验证,只返回一个第二层的函数名(验证函数的函数名)      @login                 #还未到真正调用函数的地方,所以此处不需要进行登录验证,只返回第二层的函数名即可。      def america():          print("*****欧美专区*****")      @login                 #还未到真正调用验证函数的地方,所以此处不需要进行登录验证,只返回第二层函数名即可。      def henan():          print("*****河南专区*****")      america()               #调用时,执行第二层函数。因为上面已经拿到了第二层的函数名      henan()                #调用时,执行第二层函数。因为上面已经拿到了第二层的函数名

 

二、生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

  实例一:

 data = [1,2,3,4,5,6,7,8,9,]

#列表生成式(装逼的写法)data = [i*2 if i > 4 else i for i in data]print(data)==》[1, 2, 3, 4, 10, 12, 14, 16, 18]#列表生成器(数据用到的时候才生成)data2 = (i*2 if i > 4 else i for i in data)print(data2)==》<generator object <genexpr> at 0x000002797C151DB0>小结:生成器只有在调用时,才会生成相应的数据。  实例二、  import time#定义消费者模型函数def consumer(name):    print("%s 准备吃包子啦!" %name)
    while True:        baozi = yield        print("包子[%s]来了,被[%s]吃了!" % (baozi,name))#定义生产者模型函数def producer(name):    c_a = consumer("A")    c_b = consumer("B")    c_a.__next__()    c_b.__next__()    print("老子开始准备做包子了!")    for i in range(10):        time.sleep(1)        print("做了2个包子!")        c_a.send(i)        c_b.send(i)producer("alex")三、迭代器我们知道,可以直接作用于for循环的数据类型有以下几种:一类是集合数据类型:如list,tuple,dict,set,str等;一类是 generator,包括生成器和带yield的generator函数。这些可以直接作用于for循环的对象统称为可迭代对象,Iterable可以使用isinstance()判断一个对象是否是Iterable对象:
from collections import Iterable#判断字符串是否可迭代data = "abc"print(isinstance(data,Iterable)) #===》True#判断列表是否可迭代data = [1,2,3]print(isinstance(data,Iterable)) #===》True#判断字典是否可迭代data = {1:"ye",2:"zhang",3:"alex"}print(isinstance(data,Iterable)) #===》True#判断元组是否可迭代data = (1,2,3)print(isinstance(data,Iterable)) #===》True注1:可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
注2:字典、集合、元组、字符串等都是可迭代对象,但是不是迭代器。但是可以通过iter()函数获得一个迭代器。

 

  


    

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!