zoukankan      html  css  js  c++  java
  • Python 闭包、迭代器和生成器

    1, 函数名的应用,第一类对象
    函数名可以像变量一样进行使用
    (1)赋值
    (2)作为list元素
    (3)作为参数
    (4)作为返回值

    2, 闭包
    内部函数访问外部函数的局部变量.
    好处:
    (1)安全
    (2)常驻内存. 提高效率

    name = "wusir"  # 变量写在全局是不安全的
    
    def abc():
        global name
        name ="呵呵"
    abc()
    
    def func():
        name = "alex"   # 常驻内存  防止其他程序改变这个变量
        def inner():
            print(name)  # 在内层函数中调用了外层函数的变量,叫闭包, 可以让一个局部变量常驻内存
        return inner
    ret = func()
    ret()     # 执行的是inner()
    ret()

     

    # 闭包的好处

    from urllib.request import urlopen
    def but(): content = urlopen("http://www.h3c.com/cn/").read() def inner(): print("你好啊") # return content # 在函数内部使用了外部的变量 . 闭包 print(inner.__closure__) # 查看inner是否是闭包, 如果有东西就是闭包, 没东西None就不是闭包 return inner print("加载中........")
    fn
    = but() # 这个时候就开始加载校花100 的内容 # 后⾯需要⽤到这⾥⾯的内容就不需要在执⾏⾮常耗时的⽹络连接操作了 content = fn() # 获取内容 print(content) content2 = fn() # 重新获取内容 print(content2)

     

    3, 迭代器
    可迭代对象(Iterable):内部包含__iter__().
    迭代器(Iterator): 内部含有__iter__() __next__()
    str, list, tuple, set, dict
    f, range

    迭代器的特点:
    (1)省内存
    (2)惰性机制 (只有__next__()了才会执行)
    (3)只能往下进行,不能回头

     

    # 可迭代对象: str, list, tuple, set, f, dict
    # 所有的以上数据类型中都有一个函数__iter__(), 所有包含了__iter__()的数据类型都是可迭代的数据类型 Iterable

     

    # dir()来查看一个对象,数据类型中包含了哪些东西

    lst = [1,2,3]   # list
    print(dir(lst))
    s = "王尼玛"
    print("__iter__" in dir(s))     #True
    print("__iter__" in dir(lst))    #True
    print("__iter__" in dir(123))  #False

     

     

    #list是一个Iterable.可迭代的

    lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] #获取迭代器 it = lst.__iter__() # 迭代器往外拿元素. __next__() print(it.__next__()) # 皇阿玛 print(it.__next__()) # 皇额娘 print(it.__next__()) # 容嬷嬷 print(it.__next__()) # 紫薇 print(it.__next__()) # 迭代到最后一个元素之后. 再进行迭代就报错了 # lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] # 模拟for循环 it = lst.__iter__() while True: try: name = it.__next__() print(name) except StopIteration: # 拿完了 break lst = [1, 2, 3] from collections import Iterable # 可迭代的 from collections import Iterator # 迭代器 # isinstence(对象, 类型) 判断xx对象是否是xxx类型的 print(isinstance(lst, Iterable)) #True print(isinstance(lst, Iterator)) #False it = lst.__iter__() print(isinstance(it, Iterable)) # 判断是否是可迭代的 迭代器一定是可迭代的 print(isinstance(it, Iterator)) # 迭代器里面一定有__next__(), __iter__() print("__iter__" in dir(lst)) # 确定是一个可迭代的 print("__next__" in dir(lst)) # 确定不是一个迭代器 # f = open("01 今日内容大纲",mode="r", encoding="utf-8") # print(isinstance(f, Iterable)) # print(isinstance(f, Iterator))

     

    迭代器的特点:
    (1)省内存
    (2)惰性机制
    (3)只能往下进行,不能回头

    lst = ["哈哈", "呵呵"]
    it = lst.__iter__()
    it.__next__()
    print(it.__next__())
    print("我要吃黄瓜")

     

    生成器和生成器函数
    生成器的本质就是迭代器

    生成器的三种创建办法:
    (1)通过生成器函数
    (2)通过生成器表达式创建生成器
    (3)通过数据转换

    生成器函数:
    函数中包含了yield的就是生成器函数
    注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行

    生成器表达式:
    (结果 for 变量 in 可迭代对象 if 筛选)
    取值:
    1. __next__()
    2. send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值
    3. 可以for循环
    4. list(g)

    def func():
        print("我是周杰伦")
        yield "昆凌"     # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数
        print("我是王力宏")
        yield "李云迪???"
        print("我是笛卡尔积")
        yield "笛卡尔积是谁"
        print("你好啊")    # 最后一个yield之后如果再进行__next__() 会报错
    
    g = func()   # 通过函数func()来创建一个生成器
    print(g.__next__()) # 周杰伦
    print(g.__next__()) # 王力宏
    print(g.__next__()) # 笛卡尔积
    print(g.__next__())
    
     
    
    #return 直接返回结果. 结束函数的调用
    # yield 返回结果.可以让函数分段执行
    
     
    
    def func():
        yield 11
        yield 22
        yield 33
        yield 44
    
    g = func()  # 拿到的是生成器. 生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环
    
    for i in g:
        print(i)    # 本质上执行的是__next__()
    
    it = g.__iter__()
    while True:
        try:
            print(it.__next__())
        except StopIteration:
            break
    
     
    
    #send
    
    def func():
        print("大碴粥")
        a = yield "11"
        print(a)
        print("狗不理")
        b = yield "22"
        print(b)
        print("大麻花")
        c = yield "33"
        print(c)
    
    g = func()
    print(g.__next__()) #大碴粥 11
    print(g.send(1))  #1 狗不理 22
    print(g.send(2)) #2 大麻花 33
    print(g.send(3)) #3 报错
    
    # __next__() 可以让生成器向下执行一次
    # send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个不能用send(). 最后一个也不要传值

     

     推导式 

     

    1列表推倒式; 最终给你的是列表
    # 语法 [最终结果(变量) for 变量 in 可迭代对象]

     

    2字典推导式

    dic = {"a":"b", "c":"d"}
    # 把字典中的key:value互换 . {"b":"a", "d":"c"}
    new_dic = {dic[key]:key for key in dic}
    print(new_dic)
    
    lst1 = ["alex", "wusir", "taibai", "ritian"]
    lst2 = ['sb', "很色", "很白", "很牛"]
    # {"alex":"sb", "wusir":"很色"}
    
    dic = { lst1[i]:lst2[i] for i in range(len(lst1))} #用索引
    print(dic)

     

    3集合推导式

    lst = ["马化腾", "马化腾", "王建忠", "张建忠", "张建忠", "张雪峰", "张雪峰"]
    
    s = {i for i in lst}    # 集合推导式

     

     

  • 相关阅读:
    STM32中GPIO的8种工作模式
    robots.txt与搜索引擎
    关于《腾讯工具类APP的千年老二》的读后感
    PCB布线的操作步骤
    c语言数据库编程ODBC
    锂电池相关结构优势特点及其保护电路解析方案
    C语言中的#与##字符的作用
    PADS中Layer的描述说明
    吃了单片机GPIO端口工作模式的大亏——关于强推挽输出和准双向口(弱上拉)的实际应用
    Protel与PADS之间相关文件的转换
  • 原文地址:https://www.cnblogs.com/babyjoy/p/9332414.html
Copyright © 2011-2022 走看看