zoukankan      html  css  js  c++  java
  • python学习——装饰器、生成器、迭代器


    '''修饰器本质是函数
    定义:修饰器是给函数补充某些功能,且不影响原函数的函数。 ps:应用在已上线的程序中的改动功能必须用到。
    拿下一行的函数名作为赋给高阶函数(就是这个函数名)变量,运行一下高阶函数,然后把返回的结果返回下一行的函数名

    原则:
    1.不改变被调用函数的调用方式;
    2.不改变被调用函数的内容;

    需要的概念:
    1.函数即变量:函数也和变量一样先在内存中存储,但是是以字符串的形式,在通过加上()的形式,就在cpu中执行。
    函数和变量在内存中的存储是必须要有对应的“门牌号”的,就是函数名和变量名,
    如果名称消失,编译器就会在执行的时候把对应内存清除。
    有一个不用名的函数,lambda,但是必须要制定一个名字,其实也是一样的。
    另外,Python是按照顺序来执行的语言。而def这个是只是定义,就是存成字符串,而不涵盖执行。
    2.高阶函数:注意是函数名,不会带()的执行括号的。
    a.把一个函数名当作实参传递给另一个函数; ps1:有了高阶函数就可以实现了不修改被装饰函数而改动函数的功能
    ps2:这个其实和“函数即变量”对应在一起的,给形参传递的就是实参,函数名对应的就是内存中的一堆字符串;
    b.返回值中包含函数名;ps:教程说是这个可以不改变形式,但是我感觉其实没有关系
    3.嵌套函数:
    在一个函数内部再定义一个函数。内部定义的函数是一个局部变量(函数),可以在内部调用。
    4.@函数名:放的位置,只能是一个函数上面的第一格; ps:这个也是为什么pycharm一直提示,函数前面空两行的原因
    ,因为读取函数的时候还要看上面两行有没有别的要进来修饰
      功能:拿下一行的函数作为赋给高阶函数(就是这个函数名)变量,运行一下,然后把返回的结果返回下一行的函数名
    就是覆盖原来的函数名代表的内存位置,指到了高阶函数返回值的位置。)可以看看第四周第六章20min左右。就相当于重新定义了一个已经存在的变量来覆盖;


    # '''
     1 '''下面是装饰器'''
     2 
     3 import time
     4 
     5 
     6 def decor_fun(func):
     7     def tm_func(*para1, **para2):    #'''如果这里要实现传递参数,必须加入一个参数,然后在下面的func(参数),需要这样的,不过最好是使用非固定参数!!'''
     8         start_time = time.time()
     9         func(*para1, **para2)   #注意在这个地方的函数定义的时候,引入的函数,还是会到原来函数存储的位置去找的。所以说,修饰器其实有一新一旧两个地址,但是用户只能用新的。
    10         end_time =time.time()
    11         print("the run time is %s"%(end_time-start_time))
    12     return tm_func     #局部变量是一个块内容里面有,这里tm_func是在整个装饰器的函数里面有用,
    13     # 所以在这个地方返回就可以返回到函数的外面。
    14 
    15 
    16 
    17 @decor_fun  # 等于是将下面的函数调用变成,tst_demo = decor_fun(tst_demo),所以以后的tst_demo 对应的就是新地址;那么相当于这个新地址就是tm_func对应的内容;旧地址tst_demo还是在的,只不过用户拿不到;
    18 def tst_demo(): 19 print("we know this test demo run time is very quick") 20 time.sleep(3) 21 print("but we want to know the time!") 22 return 0 23 24 @decor_fun # 25 def try1(): 26 print("jiushi shishi") 27 time.sleep(2) 28 29 '''看看如果带入参数能够实现吗?就是输入的参数,能否被传入;结果显示是不行的,必须在装饰器那边就写上参数''' 30 def try2(name): 31 print("this is try2", name) 32 time.sleep(2) 33 34 tst_demo() 35 try1() 36 37 '''下面这个就是类似的效果''' 38 decor_fun(try2)("qie")

    高阶函数还可以有2层的函数;
     1 '''这个版本是为了学如何传递两层参数'''
     2 import time
     3 
     4 
     5 def decor_fun(*arg1):
     6     print("This out_layer", *arg1)   #遇到@符号救护先进来到这一步;
     7 
     8     def tm_func0(func):
     9         def tm_func(*para1, **para2):  # '''如果这里要实现传递参数,必须加入一个参数,然后在下面的func(参数),需要这样的,不过最好是使用非固定参数!!'''
    10             start_time = time.time()
    11             func(*para1, **para2)  # 注意在这个地方的函数定义的时候,引入的函数,还是会到原来函数存储的位置去找的。所以说,修饰器其实有一新一旧两个地址,但是用户只能用新的。
    12             end_time = time.time()
    13             print("the run time is %s" % (end_time - start_time))
    14         return tm_func  # 局部变量是一个块内容里面有,这里tm_func是在整个装饰器的函数里面有用,
    15         # 所以在这个地方返回就可以返回到函数的外面。
    16     return tm_func0
    17 
    18 
    19 @decor_fun("ky")  # 等于是将下面的函数调用变成,tst_demo = decor_fun(tst_demo),所以以后的tst_demo 对应的就是新地址
    20 def tst_demo():
    21     print("we know this test demo run time is very quick")
    22     time.sleep(3)
    23     print("but we want to know the time!")
    24     return 0
    25 
    26 
    27 @decor_fun  #
    28 def try1():
    29     print("jiushi shishi")
    30     time.sleep(2)
    31 
    32 
    33 '''看看如果带入参数能够实现吗?就是输入的参数,能否被传入;结果显示是不行的,必须在装饰器那边就写上参数'''
    34 def try2(name):
    35     print("this is try2", name)
    36     time.sleep(2)
    37 
    38 tst_demo()
    39 #try1()
    40 
    41 '''下面这个就是类似的效果'''
    42 decor_fun(try2)("qie")

    # 生成器,相当于在内存里面存储一个算法,只有调用的时候,才会在内存中出现具体的数值。
    生成器通常是应用于有规律的数据。
    #按需要一个个取出来

    分类: 列表生成器以及函数生成器


    列表生成器:
    # 形式类似于, ( i*2 for i in range(10) ) .这是是利用小括号来表示,内部是具体的算法。中括号的话,就是列表生产式。
    # 调用的方式就是使用“for i in 列表生成器” 的形式调用;
    #
    #函数生成器只有__next__()方法,没办法往前,只能往后,取完之后就没有了。
    #
    # #常见的列表生成式
    # list_generation = [i*3 for i in range(10)]
    # print(list_generation)
    #
    # #生成器的例子
    # list_generator = (i*3 for i in range(10))
    # print(list_generator)
    #
    # for i in list_generator : ###
    # if i < 10:
    # print(list_generation[i])
    # if i > 10:
    # break
    #



    # #函数的生成器
    # 过程中必须使用到yeild,原因就是它能够实现停顿记录;并且返回参数。即需要的时候才去生成取用;
    #yeild(b) 的作用是停顿记录并且返回()中的参数;

    #
    # #弄个斐波那契数列
    # def Feibonaqie(max):
    # n,a,b = 0 , 0 ,1
    # while n < max:
    # print(b)
    # a,b = b, a+b
    # n = n +1
    # '''上面这个相对于:
    # t = (b, a + b) # t是一个tuple
    # a = t[0]
    # b = t[1]'''
    # return "done"
    #
    # Feibonaqie(20)
    #

    #函数型的生成器
    def Feibonaqie_generator(max):
    n,a,b = 0 , 0 ,1
    while n < max:
    yield (b) #使用yield就是生成器了,停顿记录,并且返回结果;
    a,b = b, a+b
    n = n +1


    f = Feibonaqie_generator(20)

    print(f.__next__())
    print(f.__next__())
    print("=========") #意味着可以随时出来。而后继续操作。

    print(f.__next__())
    print("=======")

    # for i in f: #还可以用for循环来打印。
    # print(i)

    # 获取异常的信息
    while True:
    try:
    x = f.__next__()
    print('g:', x)
    except StopIteration as e:
    print('Generator return value:')
    break



     #迭代器
    """凡是可作用于for循环的对象都是Iterable(可迭代)类型;
    *可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
    集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()


    我们已经知道,可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如listtupledictsetstr等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    可以使用isinstance()判断一个对象是否是Iterable对象:

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

  • 相关阅读:
    文件操作:Directory,File,FielStream、StreamRead和StreamWriter的使用
    MVC中Excel导入
    T对象序列化后T对象中属性字段不见了?
    Sql游标
    Form表单提交
    AJAX异步删除操作
    数据库表结构导出sql语句
    多线程的使用
    找不到dll原因
    代码优化
  • 原文地址:https://www.cnblogs.com/Ian-learning/p/12715999.html
Copyright © 2011-2022 走看看