一·Python是如何進行內存管理
Python是動態類型的語言,對象與引用分離,在Python中,整數和短小的字符,Python都會緩存這些對象,以便重復使用。當我們創建多個等于1的引用時,實際上是讓所有這些引用指向同一個對象。鏈接
關鍵字:引用計數,垃圾回收,標記清除,內存池分配機制
引用:
>>> a= 10
>>> b=10
>>> print id(a),id(b),id(10)
10414060 10414060 10414060
>>>
>>> import sys
>>> print sys.getrefcount(a),sys.getrefcount(b),sys.getrefcount(10)
160 160 160
>>> c = b
>>> print sys.getrefcount(c)
159
>>> print sys.getrefcount(a)
159
>>> d= c
>>> print sys.getrefcount(d)
160
引用環:
兩個對象可能相互引用,從而構成所謂的引用環
即使是一個對象,只需要自己引用自己,也能構成引用環
>>> g = [ ]
>>> g.append(g)
>>> print sys.getrefcount(g)
3
引用減少:通過del 來減少引用 ......
垃圾回收:引用計數為0.
分代回收:存活時間越久的對象,越不可能在后面的程序中變成垃圾,所以減少在垃圾回收中掃描它們的頻率。
孤立的引用環:標記-清除
內存池機制:多層封裝管理,大內存malloc,小內存pymalloc,python對象(list,整數,浮點數)都有其獨立的內存池.
內存池:
- Python 的內存機制呈現金字塔形狀,-1,-2 層主要有操作系統進行操作;
- 第 0 層是 C 中的 malloc,free 等內存分配和釋放函數進行操作;
- 第 1 層和第 2 層是內存池,有 Python 的接口函數 PyMem_Malloc 函數實現,當對象小于256K 時有該層直接分配內存;
- 第 3 層是最上層,也就是我們對 Python 對象的直接操作;
Python 在運行期間會大量地執行 malloc 和 free 的操作,頻繁地在用戶態和核心態之間進行切換,這將嚴重影響 Python 的執行效率。為了加速 Python 的執行效率,Python 引入了一個內存池機制,用于管理對小塊內存的申請和釋放。Python 內部默認的小塊內存與大塊內存的分界點定在 256 個字節,當申請的內存小于 256 字節時,PyObject_Malloc 會在內存池中申請內存;當申請的內存大于 256 字節時,PyObject_Malloc 的行為將蛻化為 malloc 的行為。當然,通過修改 Python 源代碼,我們可以改變這個默認值,從而改變 Python 的默認內存管理行為。
調優手段(了解)
1.手動垃圾回收
2.調高垃圾回收閾值
3.避免循環引用(手動解循環引用和使用弱引用)
二·Python 引用/賦值,淺拷貝,深拷貝
賦值/引用:創建了對象的一個新的引用,修改其中任意一個變量都會影響到另一個。
淺拷貝:創建一個新的對象,但它包含的是對原始對象中包含項的引用(如果用引用的方式修改其中一個對象,另外一個也會修改改變){1,完全切片方法:a=b[::];2,工廠函數,如list();3,copy模塊的copy()函數}
深拷貝:創建一個新的對象,并且遞歸的復制它所包含的對象(修改其中一個,另外一個不會改變){copy模塊的deep.deepcopy()函數}
拷貝操作的警告 :
1、對于非容器類型,如數字,字符,以及其它“原子”類型,沒有拷貝一說。產生的都是原對象的引用。
2、如果元組變量值包含原子類型對象,即使采用了深拷貝,也只能得到淺拷貝
三·Python 單引號,雙引號,三引號的區別
單引號和雙引號是等效的,如果要換行,需要符號(),三引號則可以直接換行,并且可以包含注釋。
單引號:s4 = ‘Let\’s go’
雙引號:s5 = “Let’s go”
s6 = ‘I realy like“python”!’
四·Python 去重,排序,re模塊,lambda,tuple和list的轉換
去重:set()
排序:sorted(),list.sort()
re match與search區別
lambda:匿名函數,需要一個函數,但是又不想費神去命名一個函數,a=lambdax,y:x+y
轉換:tuple(),list()
四·Python try ... except
try下的語句正常執行,則執行else塊代碼。如果發生異常,就不會執行。
在except中return后還會執行finally中的代碼,如果存在finally語句,最后總是會執行。用 raise 方法可以拋出自定義異常。
except: #捕獲所有異常
except: <異常名>: #捕獲指定異常
except:<異常名 1, 異常名 2> : 捕獲異常 1 或者異常 2
except:<異常名>,<數據>:捕獲指定異常及其附加的數據
except:<異常名 1,異常名 2>:<數據>:捕獲異常名 1 或者異常名 2,及附加的數據
五·貪婪匹配與非貪婪匹配
String str="abcaxc";
貪婪匹配:最大長度匹配,例如去匹配str:abcaxc(ab*c)。
非貪婪匹配:就是匹配到結果就好,就少的匹配字符。例如:abc(ab*c)。
六·Python的可變與不可變數據類型
可變數據類型:列表list和字典dict;不可變數據類型:整型int、浮點型float、字符串型string和元組tuple。
不可變數據類型,不允許變量的值發生變化,如果改變了變量的值,相當于是新建了一個對象,而對于相同的值的對象,在內存中則只有一個對象,內部會有一個引用計數來記錄有多少個變量引用這個對象;
可變數據類型,允許變量的值發生變化,即如果對變量進行append、+=等這種操作后,只是改變了變量的值,而不會新建一個對象,變量引用的對象的地址也不會變化,不過對于相同的值的不同對象,在內存中則會存在不同的對象,即每個對象都有自己的地址,相當于內存中對于同值的對象保存了多份,這里不存在引用計數,是實實在在的對象。
操作不可變對象:
>>> a =(2,3)
>>> print a[1]
3
>>> a[1] =3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
七·print 調用 Python 中底層的什么方法
print 方法默認調用 sys.stdout.write 方法,即往控制臺打印字符串。
八· input()函數
在 Python3 中,input()獲取用戶輸入,不論用戶輸入的是什么,獲取到的都是字符串類型的。
在 Python2 中有 raw_input()和 input():
raw_input()和 Python3 中的 input()作用是一樣的,
input()輸入的是什么數據類型的,獲取到的就是什么數據類型的。
九· range 和 xrange 的區別
兩者用法相同,不同的是 range 返回的結果是一個列表,而 xrange 的結果是一個生成器,前者是直接開辟一塊內存空間來保存列表,后者是邊循環邊使用,只有使用時才會開辟內存空間,所以當列表很長時,使用 xrange 性能要比 range 好。
十· read、readline 和 readlines 的區別
read:讀取整個文件。
readline:讀取下一行,使用生成器方法。
readlines:讀取整個文件到一個迭代器以供我們遍歷。
十一·init 和new的區別
init 通常用于初始化一個新實例,控制這個初始化的過程,比如添加一些屬性, 做一些額外的操作,發生在類實例被創建完以后。它是實例級別的方法。
new 通常用于控制生成一個新實例的過程。它是類級別的方法。
相關鏈接
十二·模塊和包
在 Python 中,模塊是搭建程序的一種方式。每一個 Python 代碼文件都是一個模塊,并可以引用
其他的模塊,比如對象和屬性。
一個包含許多 Python 代碼的文件夾是一個包。一個包可以包含模塊和子文件夾。
十三·Python 特性
Python 是強類型的動態腳本語言:
強類型:不允許不同類型相加。
動態:不使用顯示數據類型聲明,且確定一個變量的類型是在第一次給它賦值的時候。
腳本語言:一般也是解釋型語言,運行代碼只需要一個解釋器,不需要編譯。
類型轉換:int(‘str’,base=’n’)
>>> int('0x004f',base=16)
79
解釋性語言和編譯性語言:
解釋性語言在運行程序的時候才會進行翻譯。
編譯型語言寫的程序在執行之前,需要一個專門的編譯過程,把程序編譯成機器語言(可執行文件)
十四·Python 程序運行提升性能
1、使用多進程,充分利用機器的多核性能
2、對于性能影響較大的部分代碼,可以使用 C 或 C++編寫
3、對于 IO 阻塞造成的性能影響,可以使用 IO 多路復用來解決(同一個線程內同時處理多個IO請求的目的)
4、盡量使用 Python 的內建函數
5、盡量使用局部變量
十五·Python 自省
自帶說明的名字叫自省。(反射是 java 的說法,Python叫自省)
自省簡單的說,就是用 python 的代碼自己告訴這個對象是什么,有什么,以及祖宗是什么,子孫是什么....
python 提供的自省機制:help,dir 。其他的可以用 這兩個找到
十六·Python 代碼規范(PEP8規范)
- 變量
常量:大寫加下劃線 USER_CONSTANT
私有變量 : 小寫和一個前導下劃線 _private_value(Python 中不存在私有變量,這只是程序員之間的一個約定,用于警告說明這是一個私有變量,外部類不要去訪問它。但實際上,外部類還是可以訪問到這個變量)
內置變量 : 小寫,兩個前導下劃線和兩個后置下劃線 class(前導下劃線會導致變量在解釋期間被更名。這是為了避免內置變量和其他變量產生沖突。用戶定義的變量要嚴格避免這種風格)
- 函數和方法
總體:小寫和下劃線。
私有方法 :小寫和一個前導下劃線
特殊方法 :小寫和兩個前導下劃線,兩個后置下劃線
這種風格只應用于特殊函數,比如操作符重載等。
函數參數 : 小寫和下劃線,缺省值等號兩邊無空格
類
類總是使用駝峰格式命名,所有單詞首字母大寫其余字母小寫。類名應該簡明,精確,并足以從中理解類所完成的工作。常見的一個方法是使用表示其類型或者特性的后綴模塊和包
除特殊模塊 init 之外,模塊名稱都使用不帶下劃線的小寫字母。參數
不要用斷言來實現靜態類型檢測。
不要濫用 *args 和 **kwargs。其他
1.使用 has 或 is 前綴命名布爾元素
is_connect = True
2.驗證腳本
可以安裝一個 pep8 腳本用于驗證你的代碼風格是否符合 PEP8
1-5:原文鏈接
6-15:《黑馬程序員》