zoukankan      html  css  js  c++  java
  • 函数进阶——闭包,装饰器,生成器,迭代器

    • 闭包
      • 函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问他们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含他们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
    • 装饰器
      • 在不修改原函数的情况下,给原函数增加新的功能,使得程序变得可扩展
      • http://www.cnblogs.com/alex3714/articles/5765046.html(转)
    • 列表生成式
      • 1 a = [i+1 for i in range(10)]
        2 print(a)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        View Code
    • 生成器(generator)
      • 按照一定的算法,在循环的过程中不断推算出后续的元素,可以避免创建完整的list,从而节省大量的空间
      • 创建方式
      • (1)方式一:把列表生成式中的[]换成()通过next()函数获得generator的下一个返回值,直到计算到最后一个元素,没有更多的元素时,抛出StopInteration的错误
      • 1 a = (i+1 for i in range(10))
        2 print(a)#<generator object <genexpr> at 0x0000000001E0B8E0>
        3 print(next(a))#1
        4 print(next(a))#2
        5 print(next(a))#3
        View Code
      • (2)generator 是可迭代对象,可用for循环遍历,且不用担心会报错,因此next()基本不用
      • 1 a = (i+1 for i in range(10))
        2 print(a)#<generator object <genexpr> at 0x0000000001E0B8E0>
        3 for i in a:
        4     print(i)
        View Code
      • (3)方式二:函数,在函数中添加yield,函数就变成了generator
      •  1 #斐波拉契数列
         2 def fib(max):
         3     n,a,b = 0,0,1
         4     while n < max :
         5         yield(b)#把函数的执行过程冻结在这一步,并且把b的值,返回给外面的next()
         6         a,b = b,a+b
         7         n += 1
         8     return "DONE"
         9 a = fib(5)
        10 print(fib(5))#<generator object fib at 0x0000000001DEB8E0>
        View Code
      • (4)yield  VS return
        • return返回并中止函数,return在生成器里,代表生成器的中止,直接报错
        • yield返回数据,并冻结当前的执行过程
        • next唤醒冻结的函数执行过程,继续执行,直到遇到了下一个yield
      • (5)在python2中,range = list,xrange = 生成器,在python3中,range = 生成器,xrange:没有
    • 迭代器
      • 可迭代对象Iterable:可以直接作用域for循环的对象统称为可迭代对象
        • list,tuple,dict,set,str
        • generator,包括生成器和yield的generator function
        • 可以使用isinstance()来判断一个对象是否是Interable对象
        • 1 from collections import Iterable
          2 print(isinstance([],Iterable))#True
          3 print(isinstance({},Iterable))#True
          4 print(isinstance("abc",Iterable))#True
          5 print(isinstance((x for x in range(10)),Iterable))#True
          6 print(isinstance(100,Iterable))#False
          View Code
      • 迭代器Iterator:可以被next()函数调用并不断返回下一个值的对象称为迭代器
        • 生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator
        • 可以使用isinstance()判断一个对象是否是Iterator对象:
        • 1 from collections import Iterator
          2 print(isinstance([],Iterator))#False
          3 print(isinstance({},Iterator))#False
          4 print(isinstance("abc",Iterator))#False
          5 print(isinstance((x for x in range(10)),Iterator))#True
          6 print(isinstance(100,Iterator))#False
          View Code

          解释:python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIeteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前直到序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的

        • Iter()函数:把list,dict,str等Iterable变成Iterator
        • 1 from collections import Iterator
          2 print(isinstance(iter([]),Iterator))#True
          3 print(isinstance(iter("abc"),Iterator))#True
          View Code
        • 小结
          • 凡是可作用于for循环的对象都是Iterable类型;
          • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列
          • 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象
          • python的for循环本质上就是通过不断调用next()函数实现的。
  • 相关阅读:
    软件 = 程序 + 软件工程(构建之法读书笔记一)
    网站系统开发需要掌握的技术
    C++迪杰斯特拉算法求最短路径
    strcpy函数在VS2015无法使用的问题
    C++哈夫曼树编码和译码的实现
    java学习中一些疑惑解答(2)
    凯撒加密、解密算法
    利用DOS批处理实现定时关机操作
    C及C++中typedef的简单使用指南
    java学习中的一些疑惑解答
  • 原文地址:https://www.cnblogs.com/GraceZ/p/7956201.html
Copyright © 2011-2022 走看看