zoukankan      html  css  js  c++  java
  • Python函数二(函数名,闭包,迭代器)之杵臼之交

    函数名的使用

    • 函数名可以作为值,赋值给变量。
    • 函数名可以作为参数传参给函数。
    • 函数名可以作为返回值。
    • 函数名可以作为元素存储在容器里。

    闭包

    在嵌套函数内,使用外层局部变量(非全局变量)就是一个闭包,闭包可以多层嵌套。
    闭包的优点:

    • 避免局部变量不被外界修改。
    • 函数生命周期延长。
    • 节省开辟空间,销毁空间的时间。

    闭包的作用:就是使一个局部变量常驻内存,方便后面程序调用。
    使用__closure__查看一个函数是否是闭包:

    def func1():
        str_ = "我是闭包" # 局部变量
        def func2():
            print(str_) # 使用局部变量,闭包
        func2()
        print("fun2:",func2.__closure__) # 打印func2是否是闭包
    func1() print("fun1:",func1.__closure__) # 打印内容如下 我是闭包 fun2: (<cell at 0x0000000002F52B58: str object at 0x00000000031BEAC0>,) fun1: None

    通过打印可以看出fun2是闭包。
    闭包的调用:

    def func1():
        str_ = "我是闭包" # 局部变量
        def func2():
            print(str_) # 使用局部变量,闭包
        return func2   # 返回的是函数地址
        
    func1()()
    # 打印内容如下
    我是闭包

    闭包的简单示例:

    from urllib.request import urlopen
    def reptile():
        # 获取URL所有内容
        content = urlopen("https://www.baidu.com").read()
        def get_content():
            return content
        return get_content
    get_closure = reptile()    # 获取闭包
    content = get_closure()   # 获取内容
    print(content.decode('utf-8'))   # 解码显示
    # 打印内容如下
    <html>
    <head>
        <script>
            location.replace(location.href.replace("https://","http://"));
        </script>
    </head>
    <body>
        <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>
    </body>
    </html>

    迭代器

    iterable表示可迭代的对象,遵守可迭代协议使用dir(对象)可以查看数据类型是否符合可迭代协议。dir(对象)可以获取对象所有的方法,如果方法中有__iter__说明对象遵守可迭代协议,是可迭代类型数据,如下:

    s = "Hello World"
    print(dir(s))
    
    #打印内容如下:
    '__init_subclass__', '__iter__', '__le__', ' # 这里只打印部分内容

    还可以通过isinstance(对象,参数)来检测是可迭代对象还是迭代器,如果返回结果为True是可迭代对象,如果False不是可迭代对象。

    下面是对常见数据类型的打印:

    num = 10
    bool_t = True
    str_1 = "Hello World"
    list_1 = [1,2,3]
    tuple_1 = (1,2,3)
    dict_1 = {"电影":"黄飞鸿","电视剧":"上海滩"}
    set_1 = {1,2,3,4}
    from collections.abc import Iterable
    print("int:",isinstance(num,Iterable))
    print("str:",isinstance(str_1,Iterable))
    print("bool:",isinstance(bool_t,Iterable))
    print("list:",isinstance(list_1,Iterable))
    print("tuple:",isinstance(tuple_1,Iterable))
    print("dict:",isinstance(dict_1,Iterable))
    print("set:",isinstance(set_1,Iterable)) 
    print("range:",isinstance(range(10),Iterable)) 
    
    #打印结果如下
    int: False 
    str: True 
    bool: False 
    list: True 
    tuple: True 
    dict: True 
    set: True 
    range: True 

    由此可以得出,可迭代对象:有str、list、dict、set、tuple、range()。

    迭代器:可迭代对象使用__iter__方法创建一个对象,这个对象中含有__next__方法,我们就把这个对象称为迭代器。在迭代器中可以使用__next__方法来获取迭代器中的元素,如下:

    str_1 = "Hello World"
    from collections.abc import Iterable,Iterator
    print(isinstance(str_1,Iterator)) # 查看是否是迭代器
    str_iter = str_1.__iter__() # 创建迭代器
    print(isinstance(str_iter,Iterator)) # 查看是否是迭代器
    
    #打印结果如下:
    False 
    True 

    由此可以证明上面的结论,可迭代对象并不是迭代器,需要通过__iter__方法创建迭代器对象,迭代器对象才是迭代器。

    for循环的工作原理就是通过迭代器来实现的。

    下面来看个简单的迭代器

    str_1 = "Hello" 
    str_iter = str_1.__iter__()
    print(str_iter.__next__())
    print(str_iter.__next__())
    print(str_iter.__next__())
    print(str_iter.__next__())
    print(str_iter.__next__())
    
    #打印内容如下:
    H 
    e 
    l 
    l 
    o 

    由上面的输出可以看出与for循环的输出类似,并且迭代器是不可回退的,但是当我们的迭代器超过字符串的长度后会报错StopIteration,那在使用for循环时for是怎么知道对象的长度,并且不会报错的呢?
    下面我们用while循环和迭代器模拟for循环的内部机制。

    str_1 = "Hello"
    str_iter = str_1.__iter__()
    while True:
      try: # 捕获异常
        print(str_iter.__next__()) # 打印迭代器内容
      except StopIteration: # 处理异常
        break
    
    #打印内容如下:
    H 
    e 
    l 
    l 
    o 

    注意:迭代器只能向下执行不能回退,并具有惰性,每次只获取一条数据。

    小结:

    Iterable:可迭代对象, 内部包含__iter__()方法。        
    Iterator:迭代器, 内部包含__iter__() 同时包含__next__()。 

    迭代器的特点:

    • 节省内存(不一次性加载全部数据,使用数据时,每次只获取一条数据)。
    • 惰性机制(每次只获取一条数据)。
    • 不能反复执行,只能向下执行。

    下一篇:生成器,推导式:https://www.cnblogs.com/caesar-id/p/10316858.html

  • 相关阅读:
    Java 泛型初识
    Java 设计模式之装饰模式
    深入理解Java 虚拟机 之垃圾收集器与内存分配策略
    (转)MySQL字段类型
    Eclipse 远程调试
    深入理解Java 虚拟机 之自动内存管理
    JAVA对象向上转型和向下转型
    JavaSE(二)之变量与常量、运算符、类型转换
    Maven(四)之archetype插件的使用
    Hibernate(五)之一对多&多对一映射关系
  • 原文地址:https://www.cnblogs.com/caesar-id/p/10311931.html
Copyright © 2011-2022 走看看