• 巨蟒python全栈开发-第11天 第一类对象 闭包 迭代器


    一.今日主要内容总览(重点)

    1.第一类对象->函数名=>变量名
    (1)函数对象可以像变量一样进行赋值
    (2)还可以作为列表的元素进行使用
    (3)还可以作为返回值返回
    (4)还可以作为参数进行传递

    思想:函数名就是变量名
    (不仅指向一块空间,还有自身的意义)

    2.闭包->函数的嵌套
    (1)内层函数对外层函数中的变量的使用
    (2)好处:
    1.保护变量不被侵害
    2.让一个变量常驻内存

    (3)如何通过代码查看一个闭包?
    __closure__: 有东西就是闭包,没东西就不是闭包

    (4)迭代器=>固定的思路.for循环
    一个数据类型中包含了__iter__函数表示这个数据是可迭代的
    dir(数据):返回这个数据可以执行的所有操作

    (5) 判断迭代器和可迭代对象的方案(野路子)
    __iter__ 可迭代的
    __iter__ __next__ 迭代器

    (6)判断迭代器和可迭代对象的方案(官方)
    from collections import Iterable, Iterator
    isinstance(对象, Iterable) 是否是可迭代的
    isinstance(对象, Iterator) 是否是迭代器


    (7)模拟for循环
    lst=[]
    #拿迭代器
    it=lst.__iter__()
    while 1:
    try:
    it.__next__()
    excep StopIteration:
    break

    #特征:
    为了保证安全,我们在内部调用
    1. 省内存(生成器)
    2. 惰性机制
    3. 只能向前. 不能后退

    作用:统一了各种数据类型的遍历

    3.迭代器->固定的思路.for循环
    for循环的底层意义

    二.今日内容大纲

    1.第一类对象

    2.闭包

    3.迭代器

    三.内容详解

    1.第一类对象

    (1)

    def fn():
        print('我叫fn')
    print(fn)#结果:<function fn at 0x0000025672D298C8>

    (2)

    def fn():
        print('我叫fn')
    fn()
    print(fn)
    gn=fn         #函数名可以进行赋值操作
    print(gn)
    gn()
    '''
    结果:
    <function fn at 0x00000185567798C8>
    <function fn at 0x00000185567798C8>
    '''

    (3)

    def func1():
        print('朱元璋')
    def func2():
        print('朱祁镇')
    def func3():
        print('徐洁')
    def func4():
        print('魏忠贤')
    #操作一
    lst=[func1,func2,func3,func4]#列表中什么都可以放,没有数据类型的限制
    print(lst)  #结果:朱元璋
    #操作二:
    lst[0]()
    #操作三:
    for el in lst:  #el是列表中的每一项.
        el()        #拿到函数,执行函数
    '''
    结果:
    朱元璋
    朱祁镇
    徐洁
    魏忠贤
    '''

    (4)

    def func1():
        print('朱元璋')
    def func2():
        print('朱祁镇')
    def func3():
        print('徐阶')
    def func4():
        print('魏忠贤')
    #操作一
    lst=[func1(),func2(),func3(),func4()]
    print(lst)
    '''
    结果:#总结:先调用每一个,因为没有返回值,只能是4个None
    朱元璋
    朱祁镇
    徐洁
    魏忠贤
    [None, None, None, None]
    '''

    (5)

    a=10
    b=20
    c=30
    lst=[a,b,c]
    print(lst)
    '''
    结果:
    [10, 20, 30]

    (6)

    a=10
    b=20
    c=30
    lst=[a,b,c]
    print(lst)
    '''
    结果:
    [10, 20, 30]
    '''
    #通过(4)和(5),发现变量和函数的操作是一样的,变量可能数据类型不同
    #函数数据类型相同,变量的每次数据类型不一定相同
    (6)#重点降临
    def wrapper():
        def inner():
            print('我的天,还可以这样?')
        print(inner)    #<function wrapper.<locals>.inner at 0x0000021F4F929950>
        # inner()
        return inner
    ret=wrapper()
    print(ret)          #<function wrapper.<locals>.inner at 0x0000021F4F929950>
    (6-1)
    def wrapper():
        def inner():
            print('我的天,还可以这样?')
        print(inner)    #<function wrapper.<locals>.inner at 0x0000021F4F929950>
        # inner()
        return inner
    ret=wrapper()
    print(ret)          ##<function wrapper.<locals>.inner at 0x0000021F4F929950>
    ret()                #我的天,还可以这样?
    #总结:在函数外部访问了函数内部的函数
    '''
    结果:
    <function wrapper.<locals>.inner at 0x000001F1B8609950>
    <function wrapper.<locals>.inner at 0x000001F1B8609950>
    我的天,还可以这样?
    '''

    (7)

    def wrapper():
        def inner():
            print('大冬瓜')
        return inner #函数名可以向返回值一样返回#返回的是inner,也就是ret
    ret=wrapper()
    ret()   #在函数外面访问了函数内部的函数
    ret()
    ret()

    结果:

    大冬瓜
    大冬瓜
    大冬瓜

    (8)

    def func1():
        print('谢晋')
    def func2():
        print('杨士奇')
    def func3():
        print('徐渭')
    def func4():
        print('柳如是')
    
    #代理函数
    #代理,也是装饰器的雏形
    def proxy(a):   #a就是变量,形参
    #函数作为参数进行传递
        #代理好处,可以加点东西
        print('我是代理')
        a()
        print('代理执行完毕')
    proxy(func1)
    proxy(func3)
    proxy(func4)
    总结:函数名就是变量名
    1.函数名可以像变量一样进行传递
    2.函数名可以作为参数进行赋值操作
    3.可以作为返回值返回
    4.可以作为参数进行传递

    2.闭包

    (1)

    def wrapper():
        name='周杰伦'
        def inner():
            print(name)#在内层函数中,使用了外层函数的局部变量
        inner()
    wrapper()
    '''
    结果:
    周杰伦
    '''

    (2)

    def wrapper():
        name='周杰伦'
        def inner():
            print(name)#在内层函数中,使用了外层函数的局部变量
        return inner    #返回函数名
    ret=wrapper()
    ret()

    对比(1)和(2)的方式

    闭包的优点:(定义:内层函数使用了外层函数的变量)

        1.可以保护变量不被其他人侵害

    2.保持一个变量常驻于内存
    (3)#注意下面的注释
    def wrapper():
        name='周杰伦'
        def inner():
            print(name) #在内层函数中使用了外层函数的局部变量
        return inner    #返回函数名
    
    ret=wrapper()  #ret是一个内层函数
    ret()   #ret是inner,在外层执行的时机是不确定的,必须保证里面的name必须存在

    (4)

    #超级简易版爬虫
    from urllib.request import urlopen #导入一个模块
    def func():
        #获取到网页中的内容,
        content=urlopen('https://www.dytt8.net/').read()
        return content.decode('gbk')
    print(func())

    (5)#把要反复打开的网站加载 到内存中,以便快速打开网站,缺点:耗内存

    #提升缓存能力版

    #解决缓存问题
    # #超级简易版爬虫
    from urllib.request import urlopen #导入一个模块
    
    #苹果系统:干掉数字签名
    # import ssl
    # ssl._create_default_https_context=ssl._create_unverified_context()
    
    def func():
        #获取到网页中的内容,当网速很慢的时候,反复的去打开这个网站,很慢
        content=urlopen('https://www.dytt8.net/').read()
        def inner():
            return  content.decode("gbk") #网页内容
        return inner
        # return content.decode('gbk')
    print('开始网络请求')
    ret=func()      #网络请求已经完毕
    print('网络请求完毕')
    print('第一次',ret()[5])
    print('第二次',ret()[5])
    
    # print('第一次',ret())
    # print('第二次',ret())
     

    3.迭代器

    (1)

    s='今天下午考试'
    for c in s:
        print(c)
    
    #主要讨论:什么是可迭代,什么是不可迭代的?

    '''

    结果:






    '''

    (2)

    for c in '哼哼哈哈':
        print(c)#正确
    
    for c in 123:
        print(c)#错误

    (3)

    dir() 可以帮助我们查看xxx数据能够执行的操作
    print(dir(str))     #__iter__
    print(dir(int))     #没有__iter__
    print(dir(list))     #有__iter__
    print(dir(dict))     #有__iter__
    print(dir(bool))     #没有__iter__
    
    for i in True:
        print(i)            #报错:'bool' object is not iterable

    (4)

    print(dir(range))
    f=open('呵呵',mode='r',encoding='utf-8')
    print(dir(f))           #正确,文件也是可迭代的
    共性:所有带有__iter__的东西都可以进行for循环,带有__iter__东西就是可迭代对象
    (5)
    lst=['贾樟柯','李安','杨德昌','王家卫']
    
    # print('__iter__' in dir(lst))   #判断迭代器是否在lst中,结果:True
    it=lst.__iter__()       #it是拿到的是迭代器
    print(it)               #列表的迭代地址:<list_iterator object at 0x0000026309647518>
    
    print(it.__next__()) #下一个
    print(it.__next__()) #下一个
    print(it.__next__()) #下一个
    print(it.__next__()) #下一个
    
    # print(it.__next__()) #报错:下一个报错,因为列表中只有4个值  StopIteration  停止迭代
    
    it=lst.__iter__()    #只能重新获取迭代器
    print(it.__next__()) #下一个,又可以用了
    总结
    1.只能向下执行,不能反复
    2.结束的时候会给我们扔来一个错误 StopIteration
    3.整合所有的数据类型进行遍历(int,bool除外)#最大的特点

    (6)超级重点

    lst=['海尔兄弟','阿童木','葫芦娃','舒克贝塔','大风车']
    #while循环模拟for循环 for el in lst:
    it=lst.__iter__()   #获取到迭代器0
    while 1:    #循环
        try:    #尝试
            el=it.__next__()  #拿数据
            print(el)
        except StopIteration:   #出了错误,意味着数据拿完了
            break       #结束循环
    总结:
    1.节省内存
    2.惰性机制
    3.不能反复,只能向下执行
    hello world!

    (7)

    官方通过代码判断是否是迭代器
    借助于两个模块,Iterator迭代器,Iterable可迭代的
    from collections import Iterator,Iterable
    lst=[1,2,3]
    print(isinstance(lst,Iterator)) #某某某是否是迭代器,False
    print(isinstance(lst,Iterable)) #某某某是否是可迭代的类型,True
    
    it=lst.__iter__()   #迭代器一定可迭代,可迭代的东西不一定是迭代器
    
    print(isinstance(it,Iterator)) #某某某是否是迭代器,False
    print(isinstance(it,Iterable)) #某某某是否是可迭代的类型,True

    结果:

    False
    True
    True
    True

    总结:有些地方还有待完善

  • 相关阅读:
    Linux和windows 查看程序、进程的依赖库的方法
    ida pro 使用
    sql server相关
    nginx 日志log_format格式
    .yml文件格式
    svn加锁设置
    包含目录、库目录、附加包含目录、附加库目录、附加依赖项之详解
    visual studio 2017 (vs2017安装)
    OpenResty编译安装
    微信扫描二维码登录网站技术原理
  • 原文地址:https://www.cnblogs.com/studybrother/p/10099977.html
Copyright © 2020-2023  润新知