zoukankan      html  css  js  c++  java
  • Python函数Day3

    一、函数名的应用

    函数名类似于特殊的变量,打印函数名就是打印函数的内存地址

     

    ① 函数名就是函数的内存地址

    def func():
        pass
    
    >>>func
    <function func at 0x000001C0BDDAF400>

     

    ② 函数名可以作为变量

    def func():
        print(666)
    
    f = func
    f()         # f() == func()

     

    ③ 函数名可以作为函数的参数传入

    def func1():
        print(666)
    
    def func2(x):
        x()             # x() == func1()
    
    func2(func1)

     

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

    def fun1():
        def fun2():
            print(666)
        return fun2
    
    f = fun1()      # f = fun2
    f()             # f() == fun2()

     

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

    def func1():
        print(111)
    
    def func2():
        print(222)
    
    def func3():
        print(333)
    
    li = [func1,func2,func3]
    for i in li:
        i()             # func1(),func2(),func3()

     

    Python中一切皆对象,函数名就是第一类对象

     

    global()    #  将所有全局变量以字典的形式返回

    a = 1
    b = 2
    c = 3
    print(globals())
    
    # 结果
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F867E586A0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Day11/exercise.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3}

     

    locals()      # 将当前作用域(当前位置)的局部变量以字典的形式返回

    def func():
        a = 1
        b = 2
        c = 3
        print(locals())
    
    >>>func()
    {'c': 3, 'b': 2, 'a': 1}

     

    LEGB

    二、闭包

    装饰器的本质就是闭包

    面试题:闭包在哪里使用?(爬虫和装饰器会用到闭包)

     

    定义:内层函数对外层函数的变量(非全局变量)的引用,并将函数名返回,这样就形成了闭包。

    子函数对父级函数的变量进行引用,并且返回函数名,就是闭包。


    函数内部定义的函数称为内部函数,内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数

    def wraaper():
        name = 'xiaoming'
        def inner():
            print(name)
        inner()
        return inner
    wraaper()
    
    # 结果
    xiaoming

     

    函数名.__closure__  

    name = 'xiaoming'
    def wraaper(args):
        def inner():
            print(args)
        inner()
        print(inner.__closure__)
        return inner
    
    wraaper(name)
    
    
    # 结果
    xiaoming
    (<cell at 0x000001CAD4F678B8: str object at 0x000001CAD4E40A30>,)

    返回None就不是闭包

    name = 'xiaoming'
    def wraaper():
        def inner():
            print(name)
        inner()
        print(inner.__closure__)
        return inner
    
    wraaper()
    
    # 结果
    xiaoming
    None

     

    闭包的作用:

      当程序执行时,遇到了函数执行,它会在内存中开辟一个空间,叫局部名称空间,随着函数的结束而消失。

      如果这个函数内部形成了闭包,那么它就不会随着函数的结束而消失,在内存中会一直存在。

     

    三、迭代器

    可迭代对象:对象内部含有__iter__方法就是可迭代对象

    可迭代对象:str(字符串)、list(列表)、dict(字典)、tuple(元组)、set(集合)、range()

     

    可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

     

    判断对象是否可迭代对象的方法:

    ① 判断__iter__是否在对象的方法中,用dir()

    dir() 查看对象内的所有属性和方法

    s = 'abcde'
    print('__iter__'in dir(s))          # dir() 查看对象内的所有属性和方法
    
    # 结果
    True

     

    ②  isinstance() 判断是否可迭代对象

    iisinstance() 判断是否属于某个已知类型,sinstance() 能判断从属于哪种类型,type()判断哪种基本数据类型

    from collections import Iterable
    li = [1,2,3,4,5]
    print(isinstance(li,Iterable))         # 判断对象是否可迭代对象

     

    迭代器:对象内部含有__iter__方法且含有__next__方法就是迭代器

     

    判断对象是否迭代器

    ① 对象是否含有__iter__和__next__方法

    li = [1,2,3,4,5]
    print('__iter__' in dir(li))
    print('__next__' in dir(li))
    
    #  结果
    True
    False

     

    ② isinstance 判断是否迭代器

    from collections import Iterator
    dic = {'a':1 ,'b':2 ,'c':3}
    print(isinstance(dic,Iterator))
    
    # 结果
    False

     

    可迭代对象是不能取值,迭代器就是通过__next__方法可以一个一个取值。

    for循环可迭代对象是for循环内部做了优化才能取值,for含有__next__方法,因为可迭代对象没有__next__方法

     

    四、可迭代对象可以转化为迭代器

    转化方法一:__iter__() 方法

    from collections import Iterator
    dic = {'a':1 ,'b':2 ,'c':3}
    itel = dic.__iter__()               # 转化为迭代器
    print(itel)                         # 打印是否迭代器
    print(isinstance(itel,Iterator))    # 判断对象是否迭代器
    
    # 结果
    <dict_keyiterator object at 0x000002049DC76868>
    True

     

    转化方法二: iter() 方法

    from collections import Iterator
    li = ['a','b','c',1,2,3]
    itel = iter(li)                     # 转化为迭代器
    print(itel)                         # 打印是否迭代器
    print(isinstance(itel,Iterator))    # 判断对象是否迭代器
    
    # 结果
    <list_iterator object at 0x0000016BEA6F7748>
    True

     

    五、迭代器的取值

    迭代器的取值方式:通过__next__()方法取值,next一次取一个值

    Iterator.__next__()

    li = ['a','b','c',1,2,3]
    itel = iter(li)                     # 转化为迭代器
    i = itel.__next__()                 # 通过__next__()方法取值
    print(i)
    i = itel.__next__()                 # 通过__next__()方法取值
    print(i)
    
    # 结果
    a
    b


    六、迭代器的好处:

    ① 可迭代对象不能取值,迭代器是可以取值的

    ② 迭代器非常节省内存 (__next__()一次就加载一个,加载下一个元素后,上一个元素就会释放掉,跟for的机制相似)

    ③ 迭代器每次在内存中只会取一个值(一个 next 对应取一个值)

    ④  迭代器单向的,不反复,一条路走到头。next下一个就找不到上一个了,只能全部取完再重新找

     

    迭代器的使用:

    ① 迭代器没索引,为了取值

    ② 数据量大的时候

     

    for 循环机制:

    ① 将可迭代对象转化为迭代器

    ② 调用__next__()方法取值

    ③ 利用异常处理停止报错

    while 循环模拟for循环的机制

    s1 = 'abcdefghijklmn'
    iter = s1.__iter__()
    
    while 1:
        try:
            print(iter.__next__())
        except StopIteration:
            break

     文件就是迭代器

  • 相关阅读:
    js类型自动转换以及==对比规则
    js改变作用域链
    cookie简单实例
    js操作cookie
    body设置margin为0
    inline-block和block元素水平居中显示
    执行git clone遇到警告解决办法
    git中各大写字母表示含义
    git命令报错
    linux.txt
  • 原文地址:https://www.cnblogs.com/st-st/p/9494389.html
Copyright © 2011-2022 走看看