一、垃圾回收机制
何为垃圾:不能被程序访问到的数据,就称之为垃圾
1.原理:引用计数
引用计数是用来记录值的内存地址被记录的次数的。每一次对值地址的引用都可以使该值的引用计数 +1,每一次对值地址的释放都可以使该值得引用计数 -1。当一个值的引用计数为0时,该值就会被系统的垃圾回收机制回收。
2.升级:分代回收
分代:根据数据存活的时间为变量划分不同等级(也就是不同的代)。
新定义的变量,放到新生代这个等级中,假设每隔1分钟扫描新生代一次,如果发现变量依然被引用,那么该对象的权重(权重本质就是个整数)加一,当变量的权重大于某个设定得值(假设为3),会将它移动到更高一级的青春代,青春代的gc扫描的频率低于新生代(扫描时间间隔更长),假设5分钟扫描青春代一次,这样每次gc需要扫描的变量的总个数就变少了,节省了扫描的总时间,接下来,青春代中的对象,也会以同样的方式被移动到老年代中。也就是等级(代)越高,被垃圾回收机制扫描的频率越低。
3.内存泄漏
在介绍内存泄漏之前我们得先引入一个概念——循环导入。
list_1 = [666]
list_2 = [888]
list_1.append(list_2) # [666, [888, [...]]]
list_2.append(list_1) # [888, [666, [...]]]
这会导致某些值得引用计数永远大于0
4.标记删除
标记:标记的过程其实就是,遍历所有的GC Roots对象(栈区中的所有内容或者线程都可以作为GC Roots对象),然后将所有GC Roots的对象可以直接或间接访问到的对象标记为存活的对象,存放到新的内存空间中。
删除:删除的过程将遍历堆中所有的对象,将之前所有的内容全部清除。
二、re模块
定义:有语法的字符串,用来匹配获取目标字符串中的指定需求字符串。
语法
单个字符
\w:字母+数字+ _(下划线)
\W:除字母+数字+ _(下划线以外的
\s:空白、制表符、换行符、回车符
\S:除空白、制表符、换行符、回车符以外的
\d:数字
\D:非数字
\n:换行符
\t:制表符
^ :取代\A,从头开始匹配,匹配到一个即结束。
$ :取代\Z,两者都放在最后,从最后开始匹配,匹配到一个即结束。
多个字符
1、. :代表除了换行符外的任意一个字符(只能匹配一行)
print(re.findall('a.c','abc a1c aAc aaaaaca\nc')) # ['abc', 'a1c', 'aAc', 'aac']
加上re.DOTALL,表示任意一个字符
print(re.findall('a.c','abc a1c aAc aaaaaca\nc',re.DOTALL)) # ['abc', 'a1c', 'aAc', 'aac', 'a\nc']
2、?:代表左边那一个字符重复0次或1次(没有也行,最多找一个)
print(re.findall('ab?','a ab abb abbb abbbb abbbbb')) # ['a', 'ab', 'ab', 'ab', 'ab', 'ab']
3、 * :代表左边那一个字符出现0次或无穷次(没有也行,有几个找几个)
print(re.findall('ab*','a ab abb abbb abbbb abbbb a1bbbbbbb')) # ['a', 'ab', 'abb', 'abbb', 'abbbb', 'abbbb', 'a']
4、+:代表左边那一个字符出现1次或无穷次
print(re.findall('ab+','a ab abb abbb abbbb abbbb a1bbbbbbb')) # ['ab', 'abb', 'abbb', 'abbbb', 'abbbb']
5、{m,n}:代表左边那一个字符出现m次到n次(最多找n个)
print(re.findall('ab{1,3}','a ab abb abbb abbbb abbbb a1bbbbbbb')) # ['ab', 'abb', 'abbb', 'abbb', 'abbb']
同时{0,1} = ?,{0,} = * ,{1,} = +
6、.* :匹配任意长度,任意的字符(贪婪匹配——不推荐)
print(re.findall('a.*c','ac a123c aaaac a *123)()c aconfuse')) # ['ac a123c aaaac a *123)()c ac']
一直匹配到最后一个符合条件的,前面所有字符串全部包含
7、.*? :非贪婪匹配
print(re.findall('a.*?c','a123c456c')) # ['a123c']
8、[ ] :匹配一个指定范围内的字符(这一个字符来自于中括号内定义的)
print(re.findall('a[0-9][0-9]c','a1c a+c a2c a9c a11c a-c acc aAc')) # ['a11c']
当-需要被当中普通符号匹配时,只能放到[ ]的最左边或最右边
print(re.findall('a[-+*]c','a1c a+c a2c a9c a*c a11c a-c acc aAc')) # ['a+c', 'a*c', 'a-c']
多个条件连续写
print(re.findall('a[a-zA-Z]c','a1c a+c a2c a9c a*c a11c a-c acc aAc')) # ['acc', 'aAc']
[ ]内的^代表取反的意思
print(re.findall('a[^a-zA-Z]c','a c a1c a+c a2c a9c a*c a11c a-c acc aAc')) # ['a c', 'a1c', 'a+c', 'a2c', 'a9c', 'a*c', 'a-c']
print(re.findall('a[^0-9]c','a c a1c a+c a2c a9c a*c a11c a-c acc aAc')) # ['a c', 'a+c', 'a*c', 'a-c', 'acc', 'aAc']
9、 | :或者
print(re.findall('compan(ies|y)','Too many companies have gone bankrupt, and the next one is my company')) # ['ies', 'y']
分组()
1.从左往右数数 ( 进行编号,自己的分组从1开始,group(0)代表匹配到的目标整体
2.(?: … ):取消所属分组,()就是普通(),可以将里面的信息作为整体包裹,但不产生分组
group()取到分组的值
剩余方法
1.替换sub
1.不参与匹配的原样带下
2.参与匹配的都会被替换为指定字符串
3.在指定字符串值\num拿到具体分组
4.其他字符串信息都是原样字符串
print(re.sub('(xxx)(.*?)(nb)',r'\3\2\1',r'xxx is nb')) # nb is xxx
2.切分split
print(re.split('\s', '123 456\n789\t000')) # ['123', '456', '789', '000']
3.re.search and re.match
re.match从头开始匹配,找不到返回None,re.search匹配整个字符串,找到即返回,找不到返回None