美文网首页
10.python的高级语法与用法、闭包

10.python的高级语法与用法、闭包

作者: tomtiddler | 来源:发表于2018-10-01 09:23 被阅读0次

    枚举其实是一个类

    from enum import Enum
    
    class VIP(Enum):
        YELLOW = 1
        GREEN = 2
        BLACK = 3
        RED = 4
    
    print(VIP.YELLOW)  # -> VIP.YELLOW
    

    枚举的意义是其名字 而不是其数值

    枚举类和普通类相比有什么优势

    表示一连串类型的方法:
    1.普通的类和字典第一个缺陷是,没有防止改变的机制。
    2.没有防止相同标签的功能

    枚举类型、枚举名称与枚举值:

    通过type函数查看

    print(type(VIP.GREEN.name))  # 枚举的名字
    print(type(VIP.GREEN))  # 枚举的类
    print(type(VIP["GREEN"])) # 枚举的类
    

    枚举类可以遍历
    廖雪峰--枚举类

    枚举的比较运算

    result = VIP.GREEN
    assert result != VIP.BLACK, "false"
    assert result is VIP.GREEN, "false"
    

    枚举可以进行相等与不等比较,不能进行大小比较。
    可以 is 比较。身份比较
    对于不同的枚举类,即使名字和值一样,也不相等。属于不同类

    枚举注意事项

    1.枚举下不能有相同的标签
    2.枚举下可以有相同的值,那么第一个类型之后的相同值的名字是第一个类型的别名!!!枚举类有装饰器@unique检查保证不重复(相同值)

    from enum import Enum # unique
    
    # @unique
    class VIP(Enum):
        YELLOW = 1
        GREEN = 2
        BLACK = 2
        RED = 4
    
    print(VIP.YELLOW)
    print(type(VIP.GREEN.name))
    print(type(VIP.GREEN))
    print(type(VIP["GREEN"]))
    
    result = VIP.GREEN
    assert result == VIP.BLACK, "false"  # 由于重复的赋值,导致两个成员值相等,并且调用BLACK返回的名字会是GREEN
    assert result is VIP.GREEN, "false"
    
    for v in VIP:  # 没有BLACK
        print(v)
    
    for v in VIP.__members__:  # 有BLACK
        print(v)
    

    很有意思,感觉有一定的实用价值。

    枚举转换

    推荐存储类型的方法:存储数字,采用枚举类来解析所存储的数字。能增加代码的可读性。
    通过数字读取枚举类的方法 -> print(VIP(1))

    枚举小结:

    Enum值可以是字符串,如果需要强制是整数,需要用到IntEnum
    枚举类用装饰器@unique检查保证不重复(相同值?)
    采用的是单例模式,所以无法实例化 -> 猜到了
    23种设计模式

    进阶内容开场白

    高阶知识用在编程哪些方面:
    包、类库的开发者。

    一切皆对象

    函数式编程
    如果用类写代码写的很繁琐,别扭,就可以考虑函数式编程
    闭包的概念
    廖雪峰--闭包--封装
    可以把一个函数作为另一个函数的参数传递进去
    也可以把一个函数作为另一个函数的返回结果。
    个人认识:主要看一个函数的运行结果是关于函数的引用还是关于函数的调用。

    什么是闭包

    个人认识:就是初次运行函数并不返回运行值,而是返回一个可调用的对象,在此调用就会返回运行值。

    # 最简单的闭包
    # 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
    def curve_pre():
        a = 25
        
        def curve(x):
            y = a * x ^ 2 + x
            return y
        return curve
    
    
    re = curve_pre()
    print(re)  # <function curve_pre.<locals>.curve at 0x7f73b9e27158>
    print(re.__closure__)  # 闭包的参数对象
    print(re.__closure__[0].cell_contents)  # 返回闭包的参数
    print(re(2))
    
    

    闭包需要调用到函数的局部变量,否则闭包意义不大。
    返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

    一个事例看闭包

    闭包 = 函数 + 环境的变量(局部变量)
    闭包的意义:保存的是一个环境 -> 不可调用后续发生变化的值。(最好是调用局部变量)
    需要注意的地方:

    def f1():
        a = 10
        def f2():
            a = 20
            print(a)
        print(a)
        f2()
        print(a)
    
    f1() # 返回 10  20  10
    

    闭包的经典误区

    def f1():
        a = 10
        def f2():
            a = 20  # 闭包内部不能定义局部变量 可以采用 a = a + 10 的方式引用外部变量
            return a
        return f2
    
    f = f1()
    print(f)
    print(f.__closure__)  # 返回None,一旦函数的内部定义赋值了局部变量,将不再形成闭包,必须引用外部变量!!!
    

    出个题,用闭包解决

    我先用非闭包解决一下

    origin = 0
    
    def go(step):
        global origin
        new_pos = origin + step
        origin = new_pos
        return origin
    
    print(go(2))
    print(go(3))
    print(go(6))
    

    再用闭包解决一下

    origin = 0
    
    def factory(pos):
    
        def move(step):
            nonlocal pos
            new_pos = pos + step
            pos = new_pos
            return new_pos
    
        return move
    
    f = factory(origin)
    
    print(f(2))
    print(f(3))
    print(f(8))
    

    自封闭性,没有取改变全局变量的值。而是自己保存上次执行完成之后的环境的变量,将变量的改变局限在函数内部。
    闭包
    如果用类,类变量就能解决此问题。

    小谈函数式编程

    factory : 工厂模式
    python的闭包强调的是保存环境变量
    javascript的闭包强调的是函数外部访问函数内部的变量
    由于闭包产生的函数以及变量是常驻内存,容易导致内存泄漏。

    相关文章

      网友评论

          本文标题:10.python的高级语法与用法、闭包

          本文链接:https://www.haomeiwen.com/subject/vwxnnftx.html