• Python函数名本质,迭代器,迭代对象,闭包


    函数名的本质

    1 函数名就是内存地址

    1 def func():
    2     print(666)
    3 print(func)   # <function func at 0x0000024E020AB950>

    2 函数名可以作为变量

    首先,我们先对一个变量进行赋值操作,最终得到c的结果
    1 a = 2
    2 b = a
    3 c = b
    4 print(c)    # 2
    同样,对函数名进行赋值操作,看能得到什么结果?
    1 def func1():
    2     print(666)
    3 f1 = func1
    4 f2 = f1
    5 print(f1)   # <function func1 at 0x00000253AA14B950>
    6 f1()        # 666
    7 f2()        # 666
    从上面的结果可知,f1,f2得到的是函数函数名,打印出来的是函数名的地址,而f1(),f2()是函数的内容,也就是函数func1()

    3 函数名可以作为函数的参数

    1 def func():
    2     print(666)
    3 def func1():
    4     func()
    5 def func2(x):
    6     x()
    7 func2(func1)   # 666

    4 函数名可以当作函数的返回值

    1 def wraaper():
    2     def inner():
    3         print('inner')
    4     return inner
    5 ret = wraaper()    # 将inner函数的地址赋给wraaper()
    6 print(ret)   # <function wraaper.<locals>.inner at 0x000002BFFD88B9D8>
    7 ret()        # inner
    1 def func2():
    2     print('in func2')
    3 
    4 def func3(x):
    5     print('in func3')
    6     return x
    7 
    8 f1 = func3(func2)    # in func3   # func2
    9 f1()       # func2()  in func2

    4 函数名可以作为容器类类型的元素

    def func1():
        print('in func1')
    
    def func2():
        print('in func2')
    
    def func3():
        print('in func3')
    
    def func4():
        print('in func4')
    
    l1 = [func1, func2, func3, func4]
    for i in l1:
        i()
    上面介绍的函数,属于第一类对象

    globals() locals()

     globals() # 返回全局变量的一个字典
    locals() # 返回 当前位置 的局部变量的字典
     1 def func1():
     2     a = 2
     3     b = 3
     4     print(globals())
     5     print(locals())
     6     def inner():
     7         c = 5
     8         d = 6
     9         print(globals())
    10         print(locals())
    11     inner()
    12 print(locals())
    13 print(globals())
    14 func1()

    闭包

    什么是闭包?内层函数对外层函数的变量(非全局变量)的引用并返回,这样就形成了闭包。

    通过下面的例子对比闭包与非闭包的区别:

    1 # 闭包
    2 def wraaper():
    3     name = 'alex'
    4     def inner():
    5         print(name)   # alex
    6     print(inner.__closure__)  # (<cell at 0x0000027D94AFA468: str object at 0x0000027D94B8C148>,)
    7     inner()
    8     return inner
    9 wraaper()
    1 # 非闭包
    2 name = 'alex'
    3 def wraaper():
    4     def inner():
    5         print(name)       # alex
    6     print(inner.__closure__)   # None
    7     inner()
    8     return inner
    9 wraaper()
     1 # 闭包
     2 name = 'alex'
     3 def wraaper(n):
     4     n = 'alex'
     5     def inner():
     6         print(n)   # alex
     7     print(inner.__closure__)  # (<cell at 0x000001F690D1A468: str object at 0x000001F690DAC180>,)
     8     inner()
     9     return inner
    10 wraaper(name)
    闭包的作用:
    当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,即局部命名空间,如果这个函数内部形成了闭包,
    那么他就不会随着函数的结束而消失

    可迭代对象

    什么是可迭代对象?先举一个例子:
    1 for i in 'abc':
    2     print(i)
    3 for i in 123:
    4     print(i)   # 报错  TypeError: 'int' object is not iterable
    从上面可以看出,整数不是可迭代对象。
    如何判断对象为可迭代对象?
    1. 对象内部含有__iter__方法就是可迭代对象
    2. 可迭代对象满足可迭代协议。
    就目前所学知识,可迭代对象主要有:str,list,dict,tuple,set,range()。
    判断一个对象是否为可迭代对象,通常有两种方法(__iter__,isinstance):

    第一种方法:

    1 s1 = 'strs'
    2 dic = {'name':'alex'}
    3 print('__iter__' in dir(s1))   # True
    4 print('__iter__' in dir(dic))  # True

    第二种方法:

    1 1 # 第二种方法:
    2 2 s1 = 'strs'
    3 3 dic = {'name':'alex'}
    4 4 from collections import Iterable
    5 5 from collections import Iterator
    6 6 print(isinstance('alex',Iterable))  # True
    7 7 print(isinstance('alex',Iterator))  # False
    8 8 print(isinstance('alex',str))       # True

    迭代器

    什么是迭代器?迭代器指对象内部含有__iter__方法且含有__next__方法就是迭代器
    1 f = open('register', encoding='utf-8')
    2 print('__iter__' in dir(f))
    3 print('__next__' in dir(f))
    4 print('__iter__' in dir(dict))
    5 print('__next__' in dir(dict))
    可迭代对象与可迭代器的比较。
    1. 可迭代对象不能取值,迭代器是可以取值的
    2. 可迭代对象 ————>(转化成)迭代器 (__iter__,iter())
    1 lis = [1,2,3] # 可迭代对象
    2 itel = lis.__iter__()  # 将列表转化为迭代器  <list_iterator object at 0x0000012DA426C1D0>
    3 print(itel)
    4 itel = iter(lis)    # # 将列表转化为迭代器  <list_iterator object at 0x000002E0BF96C198>
    5 print(itel)
    迭代器如何取值? 使用关键字next,每next一次,取一个值。
    1 lis = [1,2,3]
    2 itel = iter(lis)
    3 print(itel.__next__())
    4 print(itel.__next__())
    5 print(itel.__next__())
    6 print(itel.__next__())   # 最后一次报错
    从上可以看出,总结迭代器的特点:
    1. 可迭代对象不能取值(但可通过切片取值),迭代器是可以取值的,
    2. 迭代器非常节省内存,
    3. 迭代器每次只会取一个值,
    4. 迭代器是单向的,一条路走到头。

    for循环的工作原理

    1 s1 = 'ndsncla'
    2 for i in s1:
    3     print(i)
    for循环工作机理:
    1. 将可迭代对象转化为迭代器
    2. 调用__next__方法取值
    3. 利用异常处理停止报错
    1 s1 = 'ndsncla'
    2 s = s1.__iter__()
    3 while 1:
    4     try:
    5         print(s.__next__())
    6     except StopIteration:
    7         break
  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/colin1314/p/9495134.html
Copyright © 2020-2023  润新知