zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    服务器端接受Json数据的绑定实现
    SQL 学习笔记
    asp.net mvc下的多语言方案 包含Html,Javascript和图片
    设计和创建自己的Sharepoint Site
    SharePoint类库简要总结
    TED-谷歌创始人演示谷歌眼睛
    为什么要有战争
    跨云应用部署:共享数据存储
    使用VNET-to-VNET连接Microsoft Azure国际版和中国版
    MySQL Database on Azure新功能
  • 原文地址:https://www.cnblogs.com/colin1314/p/9495134.html
Copyright © 2011-2022 走看看