一、垃圾回收機制
何爲垃圾:不能被程序訪問到的數據,就稱之爲垃圾
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