为什么切片和区别会忽略最后一个元素?
1.当只有最后一个元素时, 可以快速看出切片和区间又有几个元素[: 3]
2.当起始位置都可见时, 可以快速计算出切片的区间长度 [start:end] end-start
3. 可以通过一个下标将列表分割为不重叠的两部分
什么是自省?
程序在运行时, 能知道对象的类型。
dir() 返回对象的属性名称排序后的列表
type() 判断对象的类型
hasattr() 查询对象是否有一个特性的属性
isinstance() 判断继承链
猴子补丁(monkey patch): 在运行时修改模块和类, 而不改动源码
例: 使用gevent模块时, from
gevent
import
monkey; monkey.patch_socket()
对socket标准库打上猴子补丁,此后socket标准库中的类和方法都会被替换成非阻塞式的
异步和同步
参考: https://www.cnblogs.com/skying555/p/5028167.html
同步和异步关注的是消息通信机制
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回,一旦调用返回,就得到返回值了。
所谓异步, 调用在发出之后,这个调用就直接返回了,所以没有返回结果.换句话说当一个异步功能调用发出后,调用者不能立刻得到结果。但是这个时候被调用者可以去执行下面的代码而不是一味的等待。
阻塞和非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起
非阻塞: 非阻塞调用指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程。
多重继承和方法解析顺序(Method Resolution Order)基于C3算法:
类都有一个名为__mro__的属性, 他的值是一个元祖, 按照方法解析顺序列出各个超类, 从当前类一致向上, 知道object类。
mro(A) = mro( A(B,C) )
Python 内存管理机制:
Cpython 垃圾回收使用的主要算法是引用计数, 分代回收和标记删除为辅。
引用计数:每个对象对统计又多少引用指向自己, 当引用计数归零时, 对象立即被销毁:CPython会在对象上调用__del__方法, 然后释放分配给对象的内存
但是引用计数的缺点时处理不了循环引用,这里使用标记清除
标记删除:首先,划分成两拨, 一拨为root object(存活组), 一拨叫unreachable(死亡组), 然后他把各个对象的引用计数复制出来,对这个副本进行引用环的摘除, 摘除完毕,将副本为0的打入死亡组, 非零的放到存活组。再对非零组的对象分析,如果非零组的对象引用到了死亡组的某个对象,就将他从死亡组中解救出来, 最终把所有的还在死亡组的对象全部杀掉, 而root object 继续存活
分代回收机制
1.默认一个对象被创建出来后, 依然存活, 则划分到下一代,
2.如果经历过这一代垃圾回收后, 依然存活, 则划分到下一代。
3.垃圾回收的顺序为,0代垃圾回收一定次数, 会触发0代和1代回收, 1代垃圾回收一定次数, 会触发0代,1代, 2代回收
可以通过gc.get_threshold gc.set_threshold来查询设置参数
python的内存机制以金字塔行,
-1,-2层主要有操作系统进行操作,
第0层是C中的malloc, free等内存分配和释放函数进行操作
第一第二层是内存池 有python的接口函数PyMem_Malloc函数, 当对象小于256K由该层直接分配内存
第三层是最上层, 也就是我们对Python对象的直接操作
在C中如果频繁的调用malloc与free时,频繁地在用户态和核心态之间进行切换,是会产生性能问题的, 在加上频繁的分配与释放小块的内存会产生内存碎片
如果请求分配的内存在1~256字节之间就使用自己的内存管理系统,否则直接使用malloc ,每次会分配一块大小为256K的大块内存
经由内存池登记的内存到最后还是会回收到内存池,并不会调用 C 的 free 释放掉.以便下次使用
谈下Python 的GIL
CPython解释器本身就不是线程安全的, 因此有全局解释器锁(GIL),一次只允许使用一个线程执行Python字节吗。
然而, 标准库中所有执行阻塞型I/O操作的函数, 在等待操作系统返回结果时都会释放GIL
谈下Python的引用机制
python 的两种引入机制 relative import 和absolute import
relative import (相对引入) 一个点表示当前目录
absolute import (绝对引入) 类似于Java的引入机制
引入的时候内部做了什么事情呢 , 1.查找相应的module, 加载module到local namespace 下次再写....
print(locals()) # 局部命名空间
print(globals()) # 全局命名空间
print(__file__) # 当前module的绝对路径
print(__name__) # __name__这个系统变量显示了当前模块执行过程中的名称,如果当前程序运行在这个模块中,__name__ 的名称就是__main__如果不是,则为这个模块的名称。
import sys
print(sys.modules) # sys.modules 用于缓存,避免重复 import 带来的开销
深拷贝与浅拷贝的区别
复制列表使用内置的类型构造方法,默认浅复制, 同样[:]
浅copy只copy一层, 如果列表中有可变元素, 会共享内存地址
HTTP方法
POST 新建资源
GET 获取资源
PUT 更新资源
DELETE 删除一个资源