Python精进之路

本专题的内容结构:

unit1:精进的Python语法:

    (1),上下文管理器:

        上下文Conteext:程序执行中的某个状态

            >程序执行所需的一些内外部参数,构成了程序运行时状态

            >上下文是用来表达程序运行状态的概念,对应内存状态

            >上下文是程序中断保留或恢复运行的重要状态信息

        上下文管理器:一个可以在程序中加载独立上下文的对象

            >万物皆对象:上下文管理器也是一个对象,管理着一个独立上下文区域

                简单说就是在程序中可以停止程序,运行程序的对象

            >上下文管理器使用with 显示创建

            >进入和退出分别对应 __enter__() 和__exit__() 方法

            

            简单实例:用它来管理文件的操作:

                with open("python123.txt",'r') as f:

                    for line in f:

                        print(line)

               

                >with结束后,文件被自动关闭

                也可以打开多个文件:

                    with open("a.txt",'r') as fi,open("b.txt",'w') as fo:

                        for line in fi:

                            fo.write(line)

                >with 结束后,两个文件都会被关闭

                因为进入(__enter__())时操作的是打开文件,所以离开时,会关闭这个操作

            自定义上下文管理器:

                class DemoClass:

                    def __init__(self,name):

                        self.name= name

                    def __enter__(self):

                        print("进入上下文管理器")

                        return self

                    def __exit__(self, exc_type, exc_val, exc_tb):

                        print("退出上下文管理器")

                    def run(self):

                        print("DemoClass 的某个实例对象在运行")

                with DemoClass("python123") as d:

                    d.run()   

                输出:

                    进入上下文管理器

                    DemoClass 的某个实例对象在运行

                    退出上下文管理器

                注:如何使用上下文管理器:

                    >1,with要配合特定对象使用

                    >2,Python支持:

                        file,

                        decimal.Context,

                        thread.LockType,

                        threading.Lock,

                        threading.RLock,

                        threading.Condition,

                        threading.Semaphore,

                        threading.BoundedSempahore

                    >用户也可自定义对象

                自定义的open类:

                    class MyOpenClass:

                        def __init__(self,name,mode):

                            self.name= name

                            self.mode= mode

                        def __enter__(self):

                            print("进入上下文管理器")

                            if self.mode == 'r':

                                self.f = open(self.name,self.mode)

                            else:

                                self.f= open(self.name,self.mode)

                            return self #重点,要将self, 它返回的就是as 后面的那个

                        def __exit__(self, exc_type, exc_val, exc_tb):

                            self.f.close()

                            print("退出上下文管理器")

                        def read(self):

                            return self.f.read()

                        def write(self,s):

                            self.f.write(s)

                    with MyOpenClass("d:/test.txt",'r') as f1,MyOpenClass("d:/test02.txt",'w') as f2:

                        txt = f1.read() #从f1中读

                        print(txt)

                        f2.write(txt)  # 写到f2中去

    (2),迭代器类型:

        迭代器类型 Iterator Types :实现容器中元素的迭代:

            >Container:包含一组元素的数据类型,如 全部组合数据类型

            >迭代器:容器之上的一种迭代,迭代方式以对象形式表达

            >迭代器定义了逐一获取容器中元素的方法

        迭代器是一个对象,常与for ..in 配合使用,需要重载两个方法:

            >__iter__() 返回迭代器对象自身,配合for ..in 使用时需要

            >__next__() 返回容器的下一个元素,如果遍历结束,产生StopIteration异常

        简言之,迭代器就是一个对象有__iter__() 和__next__() 方法,还有一个异常,

            只要是有这两个方法,还有一个异常,它就是迭代器,它就可以配合for in 使用

       

        例子:

            class DemoIterator:

                def __init__(self,container):

                    self.container = container

                    self.arg = len(self.container)

                def __iter__(self):

                    return self  #必须返回自身,for in 的要求

                def __next__(self):

                    self.arg -=1

                    if self.arg >=0:

                        return self.container[self.arg]

                    else:

                        raise StopIteration

            di = DemoIterator([1,2,3,4,5,6,7,8,9])

            for i in di:

                print(i,end=',')

           

            输出:

                9,8,7,6,5,4,3,2,1,

        迭代器类型 Iterator Types:实现容器中元素的迭代

            >迭代器非常常用,尤其是涉及到管理一组数据的应用场景

            >自定义类 + for..in 管理一组数据,作为数据管理的核心自定义数据类型

            >迭代器返回下一个元素的方式为优化程序内存使用提供了重要支持

    (3),生成器类型:

        生成器 Generator:快速实现迭代器类型的方式:

            >生成器是迭代器的另一个角度诠释,生成器都是迭代器

            >生成器以逐一产生数据为角度,重点在于迭代逻辑的方便实现

            >生成器只需要yield保留字即可定义并表达,不用重载对象方法

        生成器函数 Generator Function :实现迭代逻辑的函数:

            >生成器函数是生成器的核心,用来实现迭代逻辑

            >任何包含yield语句的函数,都是生成器函数

            >对于函数来说,yield和return 功能接近,但不完全相同

            例子:

                正常的函数:

                def getVal():

                    import random

                    ls = list(range(10))

                    print(ls,end=',')

                    return ls[random.randint(0,9)]

                for i in range(10):

                    print(getVal())

                输出:

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],5

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],6

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],7

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],0

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],2

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],4

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],7

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],3

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],6

                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],5

                    注:普通函数:

                        1,每次调用完整执行后退出

                        2,如果函数表达了容器概念也如此

                        造成了计算资源浪费!它每次都重新生成一个列表

            生成器解决了这个问题:

                例子:

                    def getVal(max):

                        import random

                        ls = list(range(10))

                        print(ls,end=',')

                        for _ in range(max):

                            yield ls[random.randint(0,9)] #每调一次getVal() 就会执行一次,然后停在yield处

                    for i in getVal(10):

                        print(i)

                    输出:

                        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],1

                        5

                        7

                        4

                        7

                        5

                        9

                        3

                        7

                        9

            生成器函数的设计原则:

                >若想不断生成数据, 生成器函数需要存在迭代/循环过程

                >每次迭代/循环产生的结果以yield方式表达

                >生成器函数要与for ..in 配合使用,注意:生成器是一种特殊的迭代器

            生成器是特殊的迭代器:也有__next__(),__iter__() ,和stopIteration异常

                def getVal(max):

                    import random

                    ls = list(range(10))

                    print(ls,end=',')

                    print()

                    for _ in range(max):

                        yield ls[random.randint(0,9)]

                a = getVal(10)

                print(a.__next__())

                print(a.__next__())

                [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],

                8

                2

    (4),装饰器与语法糖:

        装饰器 Decorator:以函数为参数实现其额外功能

            >需求:对于一个已有函数,如何更新其功能?(同名使用)

            >解决方式1: 重新编写喊,把功能补充进去

            >解决方式2:不改变原来函数,增补一个装饰器给它

            原因是:有的函数是第三方库中的,有的是长期使用的函数不能随意修改它,

                所以最好的方法是额外增加功能,

            之前讲过装饰器:

                classmethod() 和staticmethod() 的内置函数(通过装饰器)

                    它们参数是函数名

                    >@classmethod 和 @staticmethod

                例子:

                    <图>

                    二者是等价的

            语法糖 Syntactic Sugar :方便使用但无实质功能的语法

                >语法糖:一种功能的简化使用方式,非功能性改变

                >Python中采用@作为语法糖,辅助装饰器使用

                >任何语法糖表达的装饰器都对应一个函数

               

                而且语法糖可以迭代使用:

                    @f2

                    def func():

                        pass

                    它等价于

                        func = f2(func)

                    这就是语法糖配合装饰器使用来简化 python代码的过程

            简单说,语法糖不重要,重要的是装饰器函数:

            装饰器设计原理 :

                >语法糖不重要,重要的是装饰器函数,该函数以函数为参数

                >由于可能存在装饰器迭代,每个装饰器函数需要返回一个函数引用

                >装饰器内部,进行功能扩展

                原始函数:

                    def func3(a):

                        print("这是变量{}".format(a))

                    func3("python123")

                现在要对它扩展功能:

                    def func1(func):

                        def wrapper(a):

                            print("我是扩展的")

                            func(a)

                            print("我也是扩展的")

                        return wrapper  #必须返回一个函数对象引用,否则无法利用语法糖

                    @func1  #等价于 func3 = func1(func3)  所以,func1一定要返回函数引用

                    def func3(a):  #这时的@func1 和def func3(a) 合起来是个新的函数

                        print("这是变量{}".format(a))

                    func3("python123")

                总结:

                    def func1(func):

                        def wrapper(a):

                            func(a)

                            print("扩展的")

                        return wrapper

                    @func1

                    def func3(a):

                        print(a)

                    func3("heello ") #其实它执行的是wrapper("hello ")

               

                装饰器的使用场景:

                    >对原函数功能的补充:测量时间,增加打印

                    >对原函数功能的调整:利用原函数运行结果,再次运算产生新的结果

                    >对原函数功能的重写:只是借助原来的名字,谨慎修改旧函数

                综合例子:

                "mx 为matrix 矩阵"

                def decorator(func):

                    def wrapper(mx1,mx2,mx1_row,mx1_col,mx2_col):

                        t1= time.perf_counter()

                        func(mx1,mx2,mx1_row,mx1_col,mx2_col)

                        print("{:.5f}".format(time.perf_counter()-t1))

                    return wrapper

                @decorator

                def mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col):

                    rst = [[0 for y in range(mx2_col)] for x in range(mx1_row)]

                    for i in range(mx1_row):  #mx1行

                        for j in range(mx1_col): # mx1列 mx2行

                            for k in range(mx2_col): #mx2列

                                rst[i][k] += mx1[i][j] *mx2[j][k]

                    return rst

                def mxsum(mx,mx_row,mx_col):

                    s = 0

                    for i in range(mx_row):

                        for j  in range(mx_col):

                            s += mx[i][j]

                    return s

                if __name__ =="__main__":

                    import time

                    mx1 = [[1,2,3],[7,8,2],[4,2,5]]

                    mx2 = [[1,2],[9,8],[11,7]]

                    mx1_row = len(mx1)

                    mx1_col = len(mx1[0])

                    mx2_row = len(mx2)

                    mx2_col = len(mx2[0])

                    rst = mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col)

                    sum1 = mxsum(mx1,mx1_row,mx1_col)

                    sum2 = mxsum(mx2,mx2_row,mx2_col)

                    print(rst)

                    print(sum1,sum2)

                    输出:

                        0.00002

                        None

                        34 38

                    我们的目的是给mxmul计时,但是输出结果里却没了计算结果:

                        这时因为我们的wrapper里没有返回计算的结果,(其实被装饰的函数已经变成了wrapper),

                            所以要把需要返回的结果返回

                        修改如下:

                            "mx 为matrix 矩阵"

                            def decorator(func):

                                def wrapper(mx1,mx2,mx1_row,mx1_col,mx2_col):

                                    t1= time.perf_counter()

                                    ret = func(mx1,mx2,mx1_row,mx1_col,mx2_col)

                                    print("{:.5f}".format(time.perf_counter()-t1))

                                    return ret

                                return wrapper

                            @decorator

                            def mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col):

                                rst = [[0 for y in range(mx2_col)] for x in range(mx1_row)]

                                for i in range(mx1_row):  #mx1行

                                    for j in range(mx1_col): # mx1列 mx2行

                                        for k in range(mx2_col): #mx2列

                                            rst[i][k] += mx1[i][j] *mx2[j][k]

                                return rst

                            def mxsum(mx,mx_row,mx_col):

                                s = 0

                                for i in range(mx_row):

                                    for j  in range(mx_col):

                                        s += mx[i][j]

                                return s

                            if __name__ =="__main__":

                                import time

                                mx1 = [[1,2,3],[7,8,2],[4,2,5]]

                                mx2 = [[1,2],[9,8],[11,7]]

                                mx1_row = len(mx1)

                                mx1_col = len(mx1[0])

                                mx2_row = len(mx2)

                                mx2_col = len(mx2[0])

                                rst = mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col)

                                sum1 = mxsum(mx1,mx1_row,mx1_col)

                                sum2 = mxsum(mx2,mx2_row,mx2_col)

                                print(rst)

                                print(sum1,sum2)

                            输出结果:

                                0.00002

                                [[52, 39], [101, 92], [77, 59]]

                                34 38

           

    (5),异步协程函数:

        协程Coroutine :在程序层面的多段代码异步执行:

            >Python3.5 新增内置功能:async ,和await保留字

            >async: 用于定义异步执行的协程代码段

            >await:异步代码段之间的手工同步方式

       

        async:

            一般可以对函数,上下文管理器和迭代器使用协程:

                async def foo():  协程函数

                    pass  

                async with lock:  协程上下文管理器

                    pass 

                async for data in pipeline: 协程迭代器

                    pass

        await:

            async def foo(db):

                data = await db.fetch("SELECT ...")

                pass

                获取异步协程的结果,结果为awaitalbe对象

            await它是在异步的函数中,等待其他函数返回结果的保留字,

        什么是awaitalbe对象,

        我们一起学习异步协程:

            >阅读:,https://www.python.org/dev/peps/pep-0492/

            >理解:理解协程产生的原因,设计方法及应用理念

            >时间:尝试定义一个协程函数并做初步分析

       

        异步协程主要应用于异步编程,多线程的场景下,

unit2:精进的Python语言:

    (1),全部保留字 :

        and or not :逻辑运算保留字

        as :对象引用保留字,相当于绑定别名

            import  as  别名(对象引用)

            try 

                except  as 对象引用

            with ... as  对象应用

        assert:

            断言语句保留字,通过异常进行程序辅助调试,

                assert 判断条件

                如果条件为False ,产生AssertionError 异常

                例如:

                    a = 10

                    try:

                        assert a<5

                    except:

                        print("a太大了")

        in :成员关系操作保留字:

            • 成员关系提取:for .. in …

            • 成员关系判断:.. in ..

        is : 对象判断保留字 只用来判断内存是否是同一块

            对象一致性判断,即比较id()函数结果

            以内存对象为判断依据:x is y

        lambda :

            • 定义匿名函数,产生函数对象

            • lambda 参数列表: 表达式  

        yield:

            • 定义一个同步或异步(协程)生成器

            • yield 表达式

        del

            • 解除引用与对象的绑定关系,“删除”引用

            • del 引用

        True /False:

            • True:表示真

            • False:表示假,含 0、0.0、[]、{} 、""等

        None: 空无保留字

            • 表示空无,与False不同

            • Python最基础的一个对象

        等等...

    (2),全部特殊符号

        特殊符号:表达Python语法的三种逻辑

        • 操作符:表达操作运算

        • 分界符:表达式之间的分界

        • 特殊含义:具有特殊含义的符号

        操作符

            + - * ** / // % @

            << >> & | ^ ~

            < > <= >= == !=

            • @ 矩阵乘法操作符 尚未有功能支持 __matmul__(),尚未支持

        分界符

            ( ) [ ] { }

            , : . ; @ = ->

            += -= *= /= //= %= @=

            &= |= ^= >>= <<= **=

           

            ; 当多行语句在一行表示时,可以用分号分隔,但不建议

            -> 函数注解,辅助对函数参数及返回值类型进行注解

                def func(a:int ,b :str) ->str:

                    return "{} and {} ".format(a,b) 

                它只是一种注解,一种约定,-> 指的是返回值是str

                func(123,"Python")

                func("Python",123)

                输出:

                    123 and Python

                    Python and 123

        Python语法不使用的符号:

            $ ? `

    (3),全部内置函数  (69)

        abs()        chr()         exec()      hex()        map()        print()    staticmethod()

        all()        classmethod() filter()    id()         max()        property() str()

        any()        compile()     float()     input()      memoryview() range()    sum()

        ascii()      complex()     format()    int()        min()        repr()     super()

        bin()        delattr()     frozenset() isinstance() next()       reversed() tuple()

        bool()       dict()        getattr()   issubclass() object()     round()    type()

        breakpoint() dir()         globals()   iter()       oct()        set()      vars()

        bytearrary() divmod()      hasattr()   len()        open()       setattr()  zip()

        bytes()      enumerate()   hash()      list()       ord()        slice()    __import__()

        callable()   eval()        help()      locals()     pow()        sorted()

原文地址:https://www.cnblogs.com/zach0812/p/11303449.html