Python 学习

基础知识

语法特性

  • ** => 取幂

  • // => 整除(舍余)

  • 赋值 => x=y=z=1 a,b=1,2

  • 没有自增、自减的写法(如:i++)

  • 数据结构 => list、tuple、set、dict

    • 不可变数据类型(值变地址变):整数(-5到256之间不改变地址)、字符串、元组

    • 可变数据类型(值变地址不变):列表、字典

  • 忽略转义符 => <str> = r'xxx\nxxx'

  • 作用域:函数内部使用 global 声明全局变量,使用 nonlocal 声明闭包上一层的函数变量

  • 匿名函数:add = lambda x,y:x+y add(1,2)

  • 异常处理:

    • try => 可能出现异常的代码

    • except => 发生异常时执行的代码

    • else => 没有异常时执行的代码

    • finally => 不管有无异常都会执行的代码

    • assert => 断言

    • raise => 手动抛异常

常用函数

文件访问模式

模式
描述

t

文本模式 (默认)

x

写模式,新建一个文件,如果该文件已存在则会报错

b

二进制模式

+

更新(读写)

U

通用换行模式(不推荐)

r

只读(默认模式),指针在开头

rb

二进制只读(默认模式),指针在开头(一般用于非文本文件如图片等)

r+

读写,指针在开头

rb+

二进制读写,指针在开头(一般用于非文本文件如图片等)

w

只写,覆盖,新建

wb

二进制只写,覆盖,新建(一般用于非文本文件如图片等)

w+

读写,覆盖,新建

wb+

二进制读写,覆盖,新建(一般用于非文本文件如图片等)

a

追加,指针在结尾,新建

ab

二进制追加,指针在结尾,新建(一般用于非文本文件如图片等)

a+

读写,指针在结尾,追加,新建

ab+

二进制读写,指针在结尾,追加,新建(一般用于非文本文件如图片等)

模式
r
r+
w
w+
a
a+

+

+

+

+

+

+

+

+

+

创建

+

+

+

+

覆盖

+

+

指针在开始

+

+

+

+

指针在结尾

+

+

不定参数

arg、*args、**kwargs

hasattr、getattr、setattr

  • hasattr() 判断对象是否包含对应的属性

  • getattr() 返回一个对象属性值

  • setattr() 设置对象的属性

闭包

迭代器

生成器(yield)

yield 返回对象,形成一个 generator 生成器,而不会结束程序

装饰器

@property

  1. 方法可以像属性一样访问

  2. 隐藏属性名,防止属性被修改

super

new

  • new 用于操作不可变对象

  • 不可变对象在 init 中很难操作,new 方法可以在 init 之前,cls 未形成 self 实例化的时候操作

setitem

getitem

回调函数

简单来说就是定义一个函数,然后将这个函数的函数名传递给另一个函数做参数,以这个参数命名的函数就是回调函数

类的特殊成员(特殊属性和特殊方法)

__repr__、__str__、__base__

__set__、__get__、__del__

继承、自定义异常

连MySQL

并发编程

进程与线程

进程是具有一定独立功能的程序在某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。

进程就是线程的集合,进程是由一个或多个线程构成的,线程是操作系统进行运算调度的最小单位,是进程中的最小运行单位。

并发与并行

并发是指多个线程对应的多条指令被快速轮换执行,处理器不断地在多个线程之间切换和执行,每个线程的执行都一定会占用这个处理器的一个时间片段,因此同一时刻其实只有一个线程被执行。

并行指同一时刻有多条指令在多个处理器上同时执行,这意味着并行必须依赖多个处理器,多个线程都是在统一时刻一起执行的。

并行只能存在于多处理器系统中,因此如果计算机处理器只有一个核,就不可能实现并行。而并发在单处理器和多处理器系统中都可以存在,因为仅靠一个核,就可以实现并发。

适用场景

  • IO密集型:线程被执行后就进入了等待状态,处理器就可以在某个线程处于等待状态的时候,去执行其他线程,从而提高整体的执行效率。

  • 计算密(CPU)集型:任务的运行一直需要处理器的参与,如果我们开启了多线程,并不会节省整体的时间,因为需要处理的任务的计算总量是不变的。此时要是线程数目过多,反而还会在线程切换的过程中耗费更多的时间,使得整体效率变低。

多线程与多进程

  • 多进程就是利用 CPU 的多核优势,在同一时间并行执行多个任务,可以大大提高执行效率。

  • Python 出于对数据安全的考虑设计了 GIL 全局解释锁,而由于 GIL锁 的限制导致不论是在单核还是多核条件下,同一时刻都只能运行一个线程,这使得 Python 多线程无法发挥多核并行的优势。

  • 在 Python 多线程下,每个线程的执行方式分如下三步:1、获取 GIL 2、执行对应线程的代码 3、释放 GIL。某个线程要想执行,必须先拿到 GIL,并且在一个 Python 进程中,GIL 只有一个,线程要是拿不到 GIL,就不允许执行。这样会导致即使在多核条件下,一个 Python 进程中的多个线程在同一时刻也只能执行一个。

  • 而对于多进程来说,每个进程都有属于自己的 GIL,所以在多核处理器下,多进程的运行是不会受 GIL 影响的。也就是说,多进程能够更好地发挥多核优势。

  • 对于 IO 密集型任务来说,多线程和多进程产生的影响差别并不大,但对于计算密集型任务来说,由于 GIL 的存在,Python 多进程的整体运行效率在多核情况下可能反而比单核更低。而 Python 的多进程相比多线程,运行效率在多核情况下比单核会有成倍提升。

  • 从整体来看,Python 的多进程比多线程更有优势。所以,如果条件允许的话,尽量用多进程。

阻塞与非阻塞

  • 阻塞状态指程序未得到所需计算资源时被挂起的状态。程序在等待某个操作完成时间,自身无法继续干别的事情,则称该程序在操作上是阻塞的。

  • 非阻塞指程序在等待某操作的过程中,自身不被阻塞,可以继续干别的事情,则称该程序在操作上是非阻塞的。

同步与异步

  • 同步指不同程序单元为了共同完成某个任务,在执行过程中需要靠某种通信方式保持协调一致,此时这些程序单元是同步执行的。

  • 异步指为了完成某个任务,有时不同程序单元之间无需通信协调也能完成任务,此时不相关的程序单元之间可以是异步的。

协程

  • 协程又称微线程、纤程,是一种运行在用户态的轻量级线程。

  • 协程拥有自己的寄存器上下文和栈。协程在调度切换时,将寄存器上下文和栈保存到其他地方,等切换回来的时候,再恢复先前保存的寄存器上下文和栈。因此,协程能保留上一次调用时的状态,即所有局部状态的一个特定组合,每次过程重入,就相当于进入上一次调用的状态。

  • 协程本质上是单个进程,相对于多进程来说,它没有线程上下文切换的开销,没有原子操作锁定及同步的开销,编程模型也非常简单。

  • 协程的用法:

    • async - 使用 async 关键字可以定义一个协程方法,这个方法在调用时不会立即被执行,而是会返回一个协程对象。

    • await - 如果协程在执行的时候遇到 await,事件循环就会将本协程挂起,转而执行别的协程,直到其他协程挂起或执行完毕。await 后面的对象必须是如下格式之一:

      • 一个原生协程对象

      • 一个由 types.coroutine 修饰的生成器,这个生成器可以返回协程对象

      • 由一个包含 __await__ 方法的对象返回的一个迭代器

    • event_loop - 事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足发生条件的时候,就调用对应的处理方法。

    • coroutine - 中文翻译叫协程,在 Python 中常指代协程对象类型,我们可以将协程对象注册到时间循环中,它会被事件循环调用。

    • task - 任务,这是对协程对象的进一步封装,包含协程对象的各个状态。

    • future - 代表将来执行或者没有执行的任务的结果,实际上和 task 没有本质区别。

  • asyncio 实现了对 TCP、UDP、SSL 协议的异步操作,而 aiohttp 实现了对 HTTP 协议的异步操作。类似于使用 requests 发起一个 HTTP 请求然后获得响应,但 requests 发起的是同步的网络请求,aiohttp 则是异步的。

Last updated