zoukankan      html  css  js  c++  java
  • DAY11 函数进阶(函数名的本质,闭包,迭代器)

    函数名的本质与一级对象:

      1.函数名表示函数的内存地址。

      2.函数名可以赋值给变量,可以作为容器数据类型的元素。

      3.函数名可以作为参数传递给函数。

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

    #一。 函数名表示函数的内存地址
    def func():
        print(111)
    print(func)     
    >>><function func at 0x00000199DFD22F28>
    
    #二。函数名可以赋值给变量,可以作为容器数据类型的元素。
    
    def func():
        print(111)
    f = func      #2.函数名可以赋值给一个变量
    f()
    >>>
    111
    
    def foo1():
        print(1)
    def foo2():
        print(2)
    def foo3():
        print(3)
    def foo4():
        print(4)
    
    l1 = [foo1,foo2,foo3,foo4] #3.函数名可以当做容器类数据类型的元素
    for i in l1:
        i()
    >>>
    1
    2
    3
    4
    
    #三。函数名可以作为参数传递给函数
    def fun1():
        print(222)
    def func2(x):
        x()
    func2(fun1)
    >>>
    222
    
    #四。函数名可以作为函数的返回值
    def func1(x):
        return x       
    def func2():
        print('in the func2')
    res = func1(func2)
    res()
    

    闭包:

      内部函数对外部作用域(非全局作用域)的变量的引用,并返回。该内部函数称为闭包函数。

    #这是闭包
    def wrapper(x):
        def inner():
            print(x)
        inner()
    wrapper('he')
    >>>
    'he'
    
    
    #这是闭包
    name = 'he'
    def wrapper(n):     
        def inner():
            print(n)
        return inner()
    wrapper(name)
    
    ##这不是闭包
    name = 'he'
    def wrapper():
        def inner():
            print(name)     #因为引用了全局作用域的变量
        return inner()
    wrapper()
    

      判断一个内部函数是不是闭包有一个好方法:"__closure__"

      (1)如果__closure__有cell为闭包函数

      (2)如果__closure__返回的是None,则不是闭包函数。

    # 这是闭包,返回有cell就是闭包
    def func():
        name = 'he'
        def inner():
            print(name)
        print(inner.__closure__)
        inner()
    func()
    >>>
    (<cell at 0x00000183451865E8: str object at 0x0000018345217810>,)
    he
    
    
    #这不是闭包,因为返回的是None
    name = 'he'
    def wrapper():
        def inner():
            print(name)
        print(inner.__closure__)
        inner()
    wrapper()
    >>>
    None
    he
    

      闭包的作用:

      # 回顾前面的知识,python解释器遇到一个函数的执行就会开辟一块新的内存空间,然后随着函数的执行结束,这块内存空间会被释放掉。但是如果一个函数被多次调用,就得多次创建内存,然后释放,再创建,再释放。。。这样对内存的损害很大

      # 但是,python解释器有一个机制,一旦检测到你的内层是一个闭包,它会在内存中开辟一块新的空间,这个空间不会随着函数的结束而释放。起到了保护内存的作用。

      闭包的嵌套:

    '''闭包嵌套'''
    def wrapper():
        money = 1000
        def func():
            name = 'he'
            def inner():
                print(name + ' have ' + str(money))
            return inner
        return func
    
    f = wrapper()
    i = f()
    i()
    

    可迭代对象(iterable)与可迭代器(iterator)

    一. 可迭代对象

      前提:在python中,可以理解成一切皆对象。

      可迭代对象:(1)对象内部含有"__iter__"方法,就是可迭代对象。

            (2)可迭代对象满足可迭代协议。

    #回顾我们学过的可迭代对象:str,list,tuple,dict,set,range()
    # dir(obj) 方法:返回一个对象的所有方法
    
    s1 = 'str'
    print(dir(s1))    #返回了字符串的所有方法
    >>>       
    ['__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']
    

      怎么判断一个对象是否为可迭代对象:

      (1)判断方法"__iter__"是否在对象的方法中,因可迭代对象都含有'__iter__'

      (2)通过isinstance(obj,type)来判读,返回True/False

         from collection  import  Iterable

         isinstance(obj,Iterabel)

    # 方法一:通过对象是否含有‘__iter__’方法
    dic = {'name':'he','age':23}
    print('__iter__' in dir(dic))
    >>>
    True
    
    
    # 方法二:通过isinstance()方法判断
    
    from collections import Iterable
    dic = {'name':'he','age':23}
    print(isinstance(dic,Iterable))
    >>>
    True

    二.迭代器(Iterator)

      迭代器:对象内部既含有"__iter__"又含有"__next__"方法的就是迭代器。

      判断一个对象是否为迭代器:

      (1)这个对象的方法中是否含有'__iter__'和'__next__'

      (2)通过isinstace(obj,type)来判断

    #我们接触过得迭代器有:文件句柄
    
    # 方法一:判断对象的方法中是否同时含有"__iter__"和"__next__"
    f = open(r'E:python_training_s1day9
    egister.txt',encoding='utf-8')
    print('__iter__' in dir(f))
    print('__next__' in dir(f))
    f.close()
    >>>
    True
    True
    
    #方法二:使用isinstance(obj,Iterator),返回True/False
    
    from collections import Iterator
    f = open(r'E:python_training_s1day9
    egister.txt',encoding='utf-8')
    print(isinstance(f,Iterator))
    f.close()
    >>>
    True
    

      

    三.可迭代对象VS迭代器

      (1)可迭代对象与迭代器有什么不同?

        1.可迭代对象不能取值(之所以能取,是python中作了优化),迭代器能够取值。

        2.迭代器非常节省内存,每次只会取一个值,在内存中只占一个内存空间。

        3.迭代器是单向的,不能够反复。

      (2)可迭代对象转换成迭代器,iterable.__iter__()

    l1 = [1,2,3] #可迭代对象
    iter_l1 = l1.__iter__()  #迭代器 iter(iterable_obj)
    print(iter_l1,type(iter_l1))
    
    print(iter_l1.__next__())
    print(iter_l1.__next__())
    print(iter_l1.__next__())
    

       (3)for循环的内部原理

        1.将可迭代对象转换为迭代器。

        2.调用__next__方法取值

        3.利用异常处理停止报错

    # 使用while循环重现for循环的原理
    
    s1 = 'abcd'
    iter1 = s1.__iter__()
    while 1:
        try:
            print(iter1.__next__())
        except Exception:
            break
    

      

     

      

  • 相关阅读:
    书_Delphi
    20160226
    SVG_style_script
    辅助
    电影_Z
    Windows下软件调试
    20160221
    Qt5.3.2_vs10_发布时所需DLL的路径
    android intent 传数据
    android 消息机制
  • 原文地址:https://www.cnblogs.com/hebbhao/p/9493634.html
Copyright © 2011-2022 走看看