python

with管理上下文

  • 我们在使用资源文件时,不管使用过程中是否发生异常,都会帮助我们执行清理操作,把资源释放。
  • 比如说文件使用后自动管理,线程中锁的自动获取和释放
  • 通过__enter__方法初始化,然后在__exit__中做善后以及异常处理
  • 使用with处理的对象必须有__enter____exit__方法

迭代器

迭代器就是可以记住遍历位置的对象

  • 迭代器从第一个元素开始访问,直到所有的元素被全部访问
  • 迭代器只能往前不能后退
  • 使用__next__来遍历
  • 调用可迭代对象的iter方法就可以得到一个迭代器
  • 可迭代对象:列表、元组、字典、集合、range、字符串
  • 文件对象本身就是迭代器

生成器

Generator

  • 生成器就是可以生成值的函数
  • 当一个函数里有了yield关键字就成了生成器
  • 生成器可以挂起执行并且保持当前执行的状态
  • 生成器是一种特殊的迭代器

生成器协程

  • 协程需要使用send(None)或者next(coroutine)来激活才能启动
  • 在yield处协程会暂停执行
  • 单独的yield value会产出值给调用方
  • 可以通过coroutine.send(value)来给协程发送值,发送的值会赋值给yield表达式
  • 协程执行完成后(没有遇到下一个yield语句)会抛出一个Stopiterration错误

装饰器

在不修改原代码的情况下,添加新的功能

  • python中一切皆对象,函数也可以当作参数传递
  • 装饰器是接受函数作为参数,添加功能后返回一个新函数的函数
  • 使用@语法糖使用装饰器
  • 类实现装饰器:重写__call__()方法

Cpython GIL

Global interpreter Lock

  • GIL的功能是:在Cpython解释器中执行的每一个线程,都会先锁住自己,阻止别的线程执行。
  • Cpython不能让一个线程一直运行独占解释器,他会轮流运行每个线程,所以cpython的并行是伪并行,其实是用快速的交替运行来模拟并行。
  • Cpython解释器的内存管理并不是线程安全的
  • 保护多线程情况下对Python对象的访问
  • Cpython使用简单的锁机制避免多个线程同时执行字节码
GIL的影响
  • 同一时间只能有一个线程执行字节码
  • CPU密集程序难以利用多核优势
  • IO期间会释放GIL,对IO密集程序影响不大
如何规避GIL影响
区分CPU和IO密集程序
  • CPU密集可以使用多进程+进程池
  • IO密集使用多线程/协程
  • cpython扩展

内存管理

GC

  • 引用计数
  • 垃圾回收
  • 标记清除
  • 分代回收
  • 内存池机制
引用计数

当我们创建一个对象时,这个对象就通过指针被变量引用,对象刚创建时,引用数为1,python中每个对象都有指向该对象的引用总数–这就是引用计数
查看对象的引用计数:sys.getrefcount()。当把一个对象作为参数传给这个函数时,实际上创建了一个临时的引用。因此,得到的结果比预期值多1.
当一个对象的引用变量名被销毁时,该对象的引用计数减少1

垃圾回收

  • 原理

当一个对象的引用数为0时,就说明没有任何变量引用该对象,那么该对象就成为要被回收的垃圾

  • 注意
  • 垃圾回收的时候,python不能执行其他的任务,
  • 只有在特定情况下python才会进行垃圾回收(垃圾少的时候没必要回收)
  • 在python运行的时候,会记录分配对象和取消分配对象的次数,当两者差值达到一定阈值的时候,垃圾回收就会启动。
  • 阈值分析
> import gc

> gc.get_threshold()
(700,10,10)
700:差值达到700的时候就会启动垃圾回收
# 10:0代回收10次后,会#对1代进行回收一次
# 10:1代回收10次后会启动一次2代回收
标记清除
  • 引用计数无法回收循环引用的问题,当AB互相引用而没有被其他对象引用,那么ab都是需要回收的,但是由于ab互相引用,引用计数不为0,就无法被回收。
  • 针对循环引用,使用标记清除机制来处理,对象之间通过引用关系连在一起,构成一个有向图,对象是这个有向图的节点,引用关系构成有向图的边。从跟对象出发,沿着有向边遍历对象,可达的对象标记为活动对象,不可达的对象就是等待清除的非活动对象。
  • 跟对象就是全局变量,调用栈,寄存器
分代回收
  • 分代回收是一种以时间换空间的操作,根据对象的存活时间分为三代,分别的年轻代、中年代、老年代。
  • 所有的新建对象都是0代
    当某一代经历过垃圾回收仍然存在就会被归入到下一代
  • 年轻代的链表总数达到上限时,python的垃圾回收就会启动

内存池

  • 对于python内置的对象,都有独立的私有内存池,对象之间的内存池不共享,即int释放的内存,不会分配给float使用
  • 大内存使用c的malloc分配,小内存使用内存池分配

缓存机制

当对象的引用计数为0时,就会被销毁并释放内存,其实实际上并不会直接被销毁,因为频繁的创建销毁会让执行效率变低。因为python引入缓存机制

引用计数为0时,把它放入到free_list链表中,之后创建的对象不会重新开辟内存,而是先从free_list中找之前的对象并初始化后来使用

  • float类型,维护的free_list链表最多可缓存100个float对象
  • int类型,不是基于free_list,而是一个small_ints保存小整数,范围-5<=value<=256。
  • 维护unicode_latinnl[256]链表,内部将所有的ASCII字符缓存起来。针对只含字母、数字、下划线组成的字符串,如果内存中已存在则不会重新创建,而是重复利用。(但是不像free_list那样一直在内存中存活,只有内存中有才会被重复利用)
  • list类型,维护的free_list数组最多可缓存80个llist对象
  • tuple类型,维护free_listt数组且数组容量20,数组中元素可以是链表且每个链表最多可以容纳2000个元组对象。
  • dict类型,维护的free_list最多可容纳80个dict对象

元类

mixin

asyncio

深浅copy

  • 浅copy是新开辟一块内存,把所有的对象的内存地址放进来
  • 深copy也是先开辟一块内存,针对可变类型和不可变类型分别处理。可变类型:在内存中重新创建一份,不可变类型:使用原来数据的内存地址
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值