zoukankan      html  css  js  c++  java
  • 函数名,闭包与迭代器

    一. 函数名的运用.    

      函数名是一个变量, 但它是一个特殊的变量, 与括号配合可以执行函数的变量.

      

      1. 函数名的内存地址

            def func():
                print("呵呵") 
            print(func) 
            结果: <function func at 0x1101e4ea0>

      

      2. 函数名可以赋值给其他变量

            def func():
                print("呵呵") 
            print(func) 
            a = func    # 把函数当成一个变量赋值给另一个变量 即是把内存地址赋值给a
            a()     # 函数调用 func()

      

      3. 函数名可以当做容器类的元素

            def func1():
                print("呵呵") 
            def func2():
                print("呵呵") 
            def func3():
               print("呵呵") 
            def func4():
               print("呵呵")
            lst = [func1, func2, func3] #当做列表的元素
            for i in lst:
                i()

      4. 函数名可以当做函数的参数

            def func():
                print("吃了么")
            def func2(fn):
                print("我是func2")
                fn()    # 执行传递过来的fn
                print("我是func2") 
            func2(func)     # 把函数func当成参数传递给func2的参数fn.

      5. 函数名可以作为函数的返回值

            def func_1():
                print("这里是函数1")
                def func_2():
                    print("这里是函数2")
                print("这里是函数1")
                return func_2 
            fn = func_1()   # 执行函数1.  函数1返回的是函数2, 这时fn指向的就是上面函数2 
            fn()    # 执行上面返回的函数
     

      

    二. 闭包

      

      1. 闭包就是内层函数,对外层函数(非全局)的变量的引用叫闭包.

            def func1():
                name = "alex"
                def func2():
                    print(name)     # 闭包
                func2() 
            func1() 
            结果: alex        

        我们可以使用__closure__来检测函数是否是闭包. 使用函数名.__closure__返回cell就是闭包,

        返回None就不是闭包

            def func1():
                name = "alex"
                def func2():
                    print(name)     # 闭包
                func2()
               print(func2.__closure__)    # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,)
             func1()     

      

      2. 如何在函数外边调用内部函数呢? 

            def outer():
                name = "alex"    # 内部函数
                def inner():
                    print(name)
                return inner 
            fn = outer()   # 访问外部函数, 获取到内部函数的函数地址 
            fn()    # 访问内部函数 

      

      3. 如果多层嵌套只需要一层一层的往外层返回就行了 

            def func1():
                def func2():
                    def func3():
                        print("嘿嘿")
                    return func3
                return func2 
            func1()()() 

           

       5.闭包的优势:

        由于我们在外界可以访问内部函数. 那这个时候内部函 数访问的时间和时机就不一定了, 因为在外部,

        我可以选择在任意的时间去访问内部函数. 这个时候. 想一想. 我们之前说过, 如果一个函数执行完毕.

        则这个函数中的变量以及局部命名空间中的内容都将会被销毁. 在闭包中.如果变量被销毁,那内部函

        数将不能正常执行. 所 以,python规定. 如果你在内部函数中访问了外层函数中的变量.那么这个变量

        将不会消亡. 将会常驻在内存中. 也就是说. 使用闭包,可以保证外层函数中的变量在内存中常驻. 

        注意: 综上, 闭包的作用就是让一个变量能够常驻内存. 供后面的程序使用. 

    三. 迭代器

      1. 我们之前一直在用可迭代对象进行迭代操作. 那么到底什么是可迭代对象. 本小节主要讨论可迭代对象.

      首先我们先回顾一下目前我们所熟知的可迭代对象有哪些: str, list, tuple, dict, set. 那为什么我们可以

      称他们为可迭代对象呢? 因为他们都遵循了可迭代协议. 什么是可迭代协议.

      首先我们先看一段错误代码:

            # 对的 
            s = "abc"
            for c in s:
                print(c) 
    
            # 错的 
            for i in 123:
                 print(i) 
            结果: 
           Traceback (most recent call last):
              File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 8, in <module>
                for i in 123: 
            TypeError: 'int' object is not iterable
         

        2. 注意看报错信息中有这样一句话. 'int' object is not iterable . 翻译过来就是整数类型对象是不可迭代的.

        iterable表示可迭代的. 表示可迭代协议. 那么如何进行验证你的数据类型是否符合可迭代协议.我们可以

        通过dir函数来查看类中定义好的所有方法. 

            s = "我的哈哈哈" 
            print(dir(s))       # 可以打印对象中的方法和函数 
            print(dir(str))     # 也可以打印类中声明的方法和函数

      在打印结果中. 寻找__iter__ 如果能找到. 那么这个类的对象就是一个可迭代对象.

      ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',

       '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__',   '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__','__mul__', '__ne__', '__new__',   '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__',   '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find',

      'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric',   'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind',   'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate',

      'upper', 'zfill']

       我们发现list, tuple, dict, set 可以进行for循环的东西都有__iter__函数, 包括range也有我们发现在字符串中

      可以找到__iter__.  

      3. 我们还可以通过isinstence()函数来查 看一个对象是什么类型的 

            l = [1,2,3] 
            l_iter = l.__iter__() 
            from collections import Iterable 
            from collections import Iterator 
            print(isinstance(l,Iterable))    #True 
            print(isinstance(l,Iterator))    #False
    print(isinstance(l_iter,Iterator)) #True
    print(isinstance(l_iter,Iterable)) #True

      综上. 我们可以确定. 如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议. 就可以获取到相应

      的迭代器. 这里的__iter__是帮助我们获取到对象的迭代器. 我们使用迭代 器中的__next__()来获取到一个迭代

      器中的元素.  

      

      4. 那么我们之前讲的for的工作原理到底是什么?

      继续看代码 

            s = "我爱北北京天安⻔门" 
            c = s.__iter__()    # 获取迭代器器 
            print(c.__next__())     # 使用迭代器进行迭代. 获取一个元素  我
    print(c.__next__()) # 爱
    print(c.__next__()) # print(c.__next__()) # print(c.__next__()) # print(c.__next__()) # print(c.__next__()) # print(c.__next__()) # StopIteration

       for循环的机制: 

            for i in [1,2,3]:
                print(i) 

       5. 使用while循环+迭代器来模拟for循环(必须要掌握)

            lst = [1,2,3] 
            lst_iter = lst.__iter__() 
            while True:
                try:
                    i = lst_iter.__next__()
                    print(i)
                except StopIteration:
                    break
     

      总结:

              Iterable: 可迭代对象. 内部包含__iter__()函数

             Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().

              迭代器的特点:

                  1. 节省内存.

                  2. 惰性机制

                  3. 不能反复, 只能向下执行.

            我们可以把要迭代的内容当成子弹. 然后呢. 获取到迭代器__iter__(), 就把子弹都装在弹夹中. 然后发射

         就是__next__()把每一个子弹(元素)打出来. 也就是说,for循环的时候.一开始的 时候是__iter__()来获取

         迭代器. 后面每次获取元素都是通过__next__()来完成的. 当程序遇到 StopIteration将结束循环.   

  • 相关阅读:
    spring 声明式事务的坑 @Transactional 注解
    这样学Linux基本命令,事半功倍
    NIO buffer 缓冲区 API
    Java技术——你真的了解String类的intern()方法吗
    Spring中配置数据源的4种形式
    Java集合框架List,Map,Set等全面介绍
    阿里面试题:关于类中静态,非静态,构造方法的执行顺序
    web.xml加载顺序
    MyBatis 延迟加载,一级缓存,二级缓存设置
    mybatis 调用存储过程
  • 原文地址:https://www.cnblogs.com/panda-pandeyong/p/9325449.html
Copyright © 2011-2022 走看看