python list转换成array_一文掌握Python【不定期更新】
目錄
一、Numpy
1 基本操作
2 隨機數
3 打亂訓練數據
4 得到元素的最值
5 拼接數組
6 得到函數的信息
7 得到累乘即各項相乘的結果
8 判斷一個數是否在數組中
9 數組的變換
10 排序
11 元素的篩選
12.保存文件/打開文件
13.限制范圍
二、PIL
1.安裝
2.PIL與Numpy的互相轉化
3.獲取Image信息
4.打開/顯示/保存圖像
5.在圖像上進行繪制
6.一些Image里面的操作
7.膨脹和腐蝕
三、OpenCV
1.安裝
2.打開/顯示/保存圖像
3.圖像尺寸變換
4.繪制文字
5.繪制半透明紅色矩形框
6.底層依賴Numpy的一些操作
7.實現圖像的JPEG質量等級壓縮
8.創建高斯模糊圖像
9.高斯模糊處理
10.一些報錯的處理
四、變量、對象、函數
1.可變對象與多進程
2.動態創建變量
3.獲取對象的所有屬性和方法
4.獲取Python占用空間的大小
5.判斷變量類型
6.文檔字符串
7.*args與**kwargs
8.pass
9.slicing
10.字符串相關
11.序列解包
12.鏈式賦值
13.增量賦值
14.斷言assert
15.with
16.list和dict查找效率比較
17.取整函數的比較
18.三元表達式(三目運算符)
19.enumerate函數
20.zip函數
21.將list轉為tuple
22.列表推導式、字典推導式、集合推導式
23.lambda及函數式編程
24.讀寫文檔
25.exec語句與eval函數
26.repr函數
27.進制等之間的轉換
28.any()函數
29.生成器
五、Python庫
1.安裝
2.單元測試unittest
3.唯一ID生成庫UUID
4.pickle
5.Flask
6.os
7.讀寫excel庫xlrd
8.platform
9.sys
10.XML解析庫xml.etree.ElementTree
11.matplotlib
12.PyTorch
13.FontTool
14.logging
15.base64
16.數據讀寫庫json與pickle
17.requests
18.CharlesShang/TFFRCNN
19.attention_ocr
六、類
1.基本概念
2.基本應用
3.元類metaclass
4.裝飾器
5.abc
6.多態
7.__str__
七、Python語言
1.什么是Python?使用Python有什么好處?
2.PEP8 Python編程規范
3.管理內存
4.靜態分析
5.Python的編譯機制
6.內存泄露問題
7.Python 2.x和Python 3.x的區別
8.單下劃線和雙下劃線
9.GIL線程全局鎖
10.sys.stdout
11.Python3的bytes/str之別
12.模塊和包
13.異常
14.猴子補丁
15.單例模式
16.字典的內部實現
17.內置算法的復雜度
18.__all__的作用
19.面向切面編程
八、深度學習相關
一、Numpy
1 基本操作
大部分簡單的操作都位于Quickstart tutorial(有一篇中文的文章Python Numpy 數組的初始化和基本操作不錯),這里列舉幾個常用的操作:
Numpy數組類是ndarray,也可以叫array。array的屬性經常用到的有兩個:
ndarray.shape:求維度大小;
ndarray.dtype:數組元素類型,比如構建RGB圖要用到的np.uint8,在構建數組時如果指定效果會更佳,后期也可以使用astype()方法轉換數據格式,比如:
>>> a = np.array([1, 2], dtype=np.float64) >>> b = a.astype(np.uint8) >>> b array([1, 2], dtype=uint8)生成array:
>>> a = np.array(1,2,3,4) # WRONG >>> a = np.array([1,2,3,4]) # RIGHT這個我的理解是需要先生成一個list,即[1,2,3,4],在將該list轉為array,我也經常用np.array(list)將列表轉為array:
a = [1,2,3,4] b = np.array(a)二維或高維list轉換成數據要注意數組不匹配的問題,即二維list每行的列數不完全相等,這樣肯定是無法轉換的。
如果想通過矩陣維度構建數據可使用np.ones()和np.zeros()兩個函數,結合之后講過的ndarray的屬性shape可構建一個與原數組相同維度的數組:
b = np.zeros(a.shape)生成純白圖像需要指定元素類型為uint8類型,因此需要特別指定元素類型:
newImg = np.ones(img.shape, np.uint8) * 255如果生成純黑圖像可以這么做:
newImg = np.zeros(img.shape, np.uint8)還有一些基本操作,比如np.exp()、np.add()等,這里不一一贅述。
淺復制與深復制。Numpy里面":"的作用與list是不同的,這里做一個實驗,對list:
>>> a = [1, 2, 3] >>> b = a[:] >>> a is b False >>> b[1] = 10 >>> a [1, 2, 3]可以看出這里是深復制。
對Numpy:
c = np.array([1, 2, 3]) >>> d = c[:] >>> c is d False >>> d.base is c True >>> d[1] = 10 >>> c array([ 1, 10, 3])可以看出這里只是淺復制,需要特別注意,深復制需要使用copy函數:
>>> e = c.copy() >>> e is a False >>> e.base is a False >>> e[2] = 5 >>> c array([ 1, 10, 3])2 隨機數
官方文檔位于Random sampling。
基本用法為:
print (np.random.random())如果要生成隨機整數,可使用numpy.random.randint函數:
print (np.random.randint(1, 2))如果要生成標準正太分布的隨機矩陣,可使用numpy.random.randn函數:
print (np.random.randn())文章也指明了正太分布與標準正太分布的關系,調用也可以使用這個關系:
設置種子,減少隨機性的影響可參考Michael:深度學習代碼復現之減少隨機性的影響。
3 打亂訓練數據
參考numpy.random.shuffle,TensorFlow里也有這個函數tf/data/Dataset,沒怎么用過,暫且記錄下。
另外還有一個函數numpy.random.permutation,與numpy.random.shuffle的作用相當,按照【Python】Numpy 中的 shuffle VS permutation的說法,numpy.random.permutation內部調用的就是numpy.random.shuffle。
4 得到元素的最值
得到元素最值很簡單,直接使用numpy.amax即可。
得到元素最值所在的下標參考numpy.argmax
例如:
>>>a array([[0, 1, 9, 3],[4, 5, 2, 8],[8, 2, 5, 1],[9, 2, 5, 5]]) >>>idx = np.argmax(a, axis=1) >>>idx array([2, 3, 0, 0])可以看出,在數組a中,第0行中最大值的下標為2,第1行中最大值的下標為3,與結果符合。
使用idx可以得到每行的最大值:
>>>a[xrange(a.shape[0]), idx] array([9, 8, 8, 9])這與numpy.amax是一致的:
>>> np.amax(a, axis=1) array([9, 8, 8, 9])5 拼接數組
numpy.column_stack等函數只提供一維或二維數組的拼接,對多維數組或需要指定維度的情況Quickstart tutorial也推薦使用numpy.concatenate,而且這個函數可以一次完成多個數組的拼接,非常棒棒了。
6 得到函數的信息
一般可以使用help(np.max)來調用np.max的信息,在使用help(np.maximum)的過程中意外發現numpy有些函數是用C語言編寫,所以Python的help()函數有時候得不到正確的函數信息,官方推薦使用下列指令來得到信息:
np.info(np.maximum)7 得到累乘即各項相乘的結果
參考【python學習筆記】23:numpy的add和multiply:
>>>np.multiply.accumulate([1,2,3,4])[-1] 24或者使用numpy.prod函數:
>>> np.prod([1, 2, 3, 4]) 248 判斷一個數是否在數組中
>>>a = np.arange(10).reshape((2, 5)) >>>9 in a True9 數組的變換
numpy.reshape非常常用,這里再介紹一個非常好用的函數numpy.swapaxes:
Interchange two axes of an array. >>>np.swapaxes(a, axis1, axis2)一個魔改方法是進行矩陣的轉置:
>>>x = np.array([[1,2,3]]) >>>np.swapaxes(x, 0, 1) array([[1],[2],[3]])增加維度可以使用numpy.expand_dims:
>>> x = np.array([1,2]) >>> x.shape (2,) >>> y = np.expand_dims(x, axis=0) >>> y array([[1, 2]]) >>> y.shape (1, 2)同樣可以刪掉特定的維度,這個可以參考請問numpy中怎么刪掉值為1的維度?:
>>> x = np.array([[[0], [1], [2]]]) >>> x.shape (1, 3, 1) >>> np.squeeze(x).shape (3,) >>> np.squeeze(x, axis=(2,)).shape (1, 3)10 排序
兩個函數,numpy.sort和numpy.argsort。
11 元素的篩選
可以過濾特定的元素:
>>>x = np.random.rand(6) >>>x array([0.28071468, 0.59360709, 0.87036219, 0.93709868, 0.4646627 ,0.27824566]) >>>x[x>0.5] >>>x array([0.59360709, 0.87036219, 0.93709868])可以賦值給特定的元素:
>>> x = np.random.rand(6) >>> x array([0.40602006, 0.58211841, 0.63038674, 0.733807 , 0.8008934 ,0.63986259]) >>> x[x>0.5] = 1 >>> x array([0.40602006, 1. , 1. , 1. , 1. ,1. ])參考Numpy where function multiple conditions,也可以使用多個條件:
>>> x = np.random.rand(6) >>> x array([0.45593443, 0.61549711, 0.88832625, 0.81612841, 0.944428 ,0.55101566]) >>> x[(x>0.6) & (x<0.9)] = 0.7 >>> x array([0.45593443, 0.7 , 0.7 , 0.7 , 0.944428 ,0.55101566])可以使用numpy.argwhere函數得到特定元素的下標:
>>>a array([[0, 1, 9, 3],[4, 5, 2, 8],[8, 2, 5, 1],[9, 2, 5, 5]]) >>>numpy.argwhere(a==9) array([[0, 2],[3, 0]])還有一個很簡單的函數numpy.any,作用,作用是排查數組中是否有真值。
12.保存文件/打開文件
參考numpy.save,保存為npy文件,保存神經網絡參數會經常用到這個,好處是不用管所用深度學習框架的模型文件,比如CharlesShang/TFFRCNN里面VGG的預訓練模型就保存在numpy文件中,與TensorFlow模型文件.ckpt的轉化可參考Michael:[代碼分享]將ckpt模型文件轉成npy模型文件。
將Numpy數據保存為圖像數據可參考將Numpy數組保存為圖像 - 純凈的天空,里面有很多硬核的方法。
13.限制范圍
參考numpy.clip - NumPy v1.16 Manual
>>> import numpy as np >>> a = np.arange(10) >>> aClip = np.clip(a, 1, 8) >>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> aClip array([1, 1, 2, 3, 4, 5, 6, 7, 8, 8])一些不錯的文章:
numpy教程:排序、搜索和計數
二、PIL
1.安裝
參考Installing PIL with pip,PIL基本已經消失了,可以使用Pillow:
pip install Pillow2.PIL與Numpy的互相轉化
PIL轉成Numpy:
參考Python(5) Image和Ndarray互相轉換:
image = np.array(imageArray)里面也提到了numpy.asarray函數與numpy.array的區別,區別在于前者是淺復制,后者是深復制:
>>> a = np.array([1, 2]) >>> b = np.array(a) >>> b is a False >>> c = np.asarray(a) >>> c is a True不過要注意這里只有當傳入的參數是array類型的時候,numpy.asarray函數才是淺復制,要不然也是深復制的:
No copy is performed if the input is already an ndarray with matching dtype and order.這里是實驗部分:
>>> b <PIL.Image.Image image mode=RGB size=200x100 at 0x7FD7993BF630> >>> c = np.array(b) >>> c is b False >>> d = np.asarray(b) >>> d is b False參考PIL中的Image和numpy中的數組array相互轉換 - 龔細軍 - 博客園,如果出現read-only錯誤,并不是轉換的錯誤,一般是你讀取的圖片的時候,默認選擇的是"r","rb"模式有關。
修正的辦法是手動修改圖片的讀取狀態:
img.flags.writeable = True # 將數組改為讀寫模式Numpy轉PIL:
參考PIL.Image.fromarray,我寫好的代碼是:
imageArray = Image.fromarray(np.uint8(image), mode="RGB")3.獲取Image信息
Image的屬性可參考Image.html#attributes,有format, size等信息。
4.打開/顯示/保存圖像
參考用python簡單處理圖片(1):打開顯示保存圖像 - denny402 - 博客園:
from PIL import Image img = Image.open(‘dog.png’) img.show() # 使用操作系統自帶的圖片瀏覽器來顯示圖像 img.save(‘dog.jpg’) # 保存圖像5.在圖像上進行繪制
可參考Pillow (PIL Fork) 3.1.2 documentation,里面有矩形、直線等的繪制方法。
這里舉個矩形的例子:
draw.rectangle([(0,300),(100,400)], fill=(0,0,255))繪制的左上角為(0, 300),右下角為(100, 400),原點位于左上角,x軸水平向右,y軸水平向下。
也可以繪制字,可能是字體繪制的原因,并不是字所有的值都與傳進的RGB值相同,邊緣會過渡至背景,這里是實驗:
from PIL import Image, ImageDraw, ImageFont >>> img = Image.new("RGB", (200, 200), (0, 0, 0)) >>> font = ImageFont.truetype("arialuni.ttf", 40) >>> d = ImageDraw.Draw(img) >>> d.text((10, 10), "hello", font=font, fill=(255, 255, 255, 255)) >>> img.show()圖片看上去很好的:
但是打印具體的值還是能發現一些問題的:
>>> import numpy as np >>> e = np.array(img) >>> e[50, :, :] array([[ 0, 0, 0],...,[ 0, 0, 0],[ 84, 84, 84],[255, 255, 255],[255, 255, 255],[255, 255, 255],[ 48, 48, 48],[ 0, 0, 0],...,[ 0, 0, 0]], dtype=uint8)從RGB過渡到灰度圖像等應用場景,如果考慮邊緣連續光滑的話可以考慮下這個問題。
6.一些Image里面的操作
縮放:參考PIL.Image.Image.resize,注意差值方法,與內存占用相關。
粘貼:參考PIL.Image.Image.paste,如果想復制RGBA圖片,可以使用mask參數。
獲取單個點的像素:參考PIL.Image.getpixel。
7.膨脹和腐蝕
OpenCV的函數對膨脹和腐蝕更友好。
參考Equivalents to OpenCV's erode and dilate in PIL?,里面也有PIL的方法:
dilation_img = src_img.filter(ImageFilter.MaxFilter(3)) erosion_img = src_img.filter(ImageFilter.MinFilter(3))一些比較好的文章:Python圖像處理庫PIL中圖像格式轉換(一)
三、OpenCV
1.安裝
使用pip安裝:
參考Ubuntu下安裝Opencv(cv2),首先搜索可用的包:
pip search opencv從中選擇合適的,我一般使用:
pip install opencv-python使用conda安裝:
conda install opencv2.打開/顯示/保存圖像
官方文檔在Getting Started with Images,中文寫的比較好的博客在openCV-Python筆記一:圖像的讀取、顯示和保存。
讀取:
img = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE)顯示:
cv2.imshow(‘image’, img) cv2.waitKey() cv2.destroyAllWindows()保存:
cv2.imwrite('1.png',img)3.圖像尺寸變換
可參考Michael:[OpenCV]遇到的一些坑(匯總貼,不經常更新)
4.繪制文字
參考puttext,遺憾是不能使用中文。在實際使用之前可以使用gettextsize函數獲取待繪制文字框的尺寸。
其它的如繪制矩形之類的可以參考同一頁面下的rectangle等函數,在此不再贅述。
5.繪制半透明紅色矩形框
參考Michael:[OpenCV]增加半透明矩形
6.底層依賴Numpy的一些操作
BGR格式轉為RGB格式:
rgb = bgr[...,::-1]沿x軸翻轉:
imgFlip = img[::-1, :, :]也可以使用官方函數flip。
旋轉90度,參考Python Opencv旋轉圖片90度:
img90 = np.rot90(img)7.實現圖像的JPEG質量等級壓縮
參考opencv實現圖像的JPEG質量等級壓縮::
img_encode = cv2.imencode('.jpeg', self.imageArray, [cv2.IMWRITE_JPEG_QUALITY, 20])[1] self.imageArray = cv2.imdecode(img_encode, cv2.IMREAD_COLOR)8.創建高斯模糊圖像
noise = np.zeros((h, w, c)) cv2.randn(noise, np.ones(3)*0, np.ones(3)*50) _print (noise) [[[-8.01547384e-08 7.90675282e+00 -3.50463986e+01][-2.14297995e+01 6.19371057e+01 -1.39004111e+01]...] >>>_print (noise.astype(np.uint8)) [[[ 0 7 221][235 61 243]...]改成uinit8的原因在于OpenCV的元素格式只能是np.uint8,另外,這里負數也會換算成對應的uint8值的,以第一行三列為例,float數為-3.50463986e+01,換算成 np.uint8為(256-3.50463986e+01)=221。
9.高斯模糊處理
模糊函數文檔位于Smoothing Images,一篇不錯的博客Python+OpenCV實現圖像高斯模糊。
高斯模糊:
arr = cv2.GaussianBlur(arr, (radius, radius), 0)均值模糊:
arr = cv2.blur(arr, (radius, radius))高斯模糊會占用過多的CPU資源,最好換成普通的Blur。
10.一些報錯的處理
/io/opencv/modules/imgproc/src/resize.cpp:3662: error: (-215:Assertion failed) func != 0 in function 'resize'n參考cv2.error: modulesimgprocsrcimgwarp.cpp:2114: error: (-215) func != 0 in function cv::resize,原因在于Array元素的精度太高,轉換成np.uint8即可:
imgArr = np.uint8(np.array(imgArr))四、變量、對象、函數
1.可變對象與多進程
參考Michael:[Python]可變對象與多進程
講述了在多進程中需要利用共享數據類型進行通信,期間講解了可變對象與不可變對象、傳參、命名空間等知識。
2.動態創建變量
如果需要創建100個變量,int1,int2,...int100,那么就可以利用locals()創建:
>>> for i in range(100): ... locals()["int%s" % i] = i ... >>> int7 73.獲取對象的所有屬性和方法
對于一個變量,參考python 獲得對象的所有屬性和方法,可通過如下方法:
>>> a = [1, 2, 3] >>> dir(a) ['__add__',..., 'reverse', 'sort']對于類,如果還想獲得屬相的值,可參考Python打印對象的全部屬性-來玩魔王的咚!-51CTO博客:
>>> class Teacher(object): ... display = "教師" # 有公有屬性 ... def __init__(self,name,age,course,salary): ... self.name = name ... self.age = age ... self.course = course ... self.__salary = salary # 也有私有屬性 >>> >>> >>> t1 = Teacher("Jerry",36,"Python",20000) >>> >>> dir(t1) ['_Teacher__salary', '__class__',..., '__weakref__', 'age', 'course', 'display', 'name'] >>> >>> t1.__dict__ {'name': 'Jerry', 'age': 36, 'course': 'Python', '_Teacher__salary': 20000}4.獲取Python占用空間的大小
參考How do I determine the size of an object in Python?,并不是很好用:
>>> import sys >>> x = 2 >>> sys.getsizeof(x) 245.判斷變量類型
參考python判斷變量類型時,為什么不推薦使用type()方法
>>>a = 111 >>>isinstance(a, int) >>>True6.文檔字符串
即docstring,作用是為函數、模塊和類注釋生成文檔。可以這么寫:
>>> def square(x): ... 'Calculates the square of the number x.' ... return x*x通過如下方式訪問:
>>> square.__doc__ 'Calculates the square of the number x.'7.*args與**kwargs
*args:往函數傳入任意個參數,或者想以列表或元組的形式傳參;
**kwargs:往函數傳入任意個關鍵詞參數,或者想以字典的值作為關鍵詞參數;
兩標識符是約定俗稱的取法,也可以使用*a和**b代替。
舉例:
>>> def print_params(x, y, z=3, *pospar, **keypar): ... print (x, y, z) ... print (pospar) ... print (keypar) ... >>> >>> print_params(1, 2, 3, 4, 5, 6, foo=1, bar=2) 1 2 3 (4, 5, 6) {'foo': 1, 'bar': 2}參數收集的逆過程:
>>> def add(x, y): ... return x + y ... >>> params = (1, 2) >>> add(*params) 3關鍵字參數是一類使用參數名提供的參數,主要作用在于可以明確每個參數的作用,每個參數的含義變得更加清晰,就算弄亂了參數的順序,對于程序的功能也沒有任何影響,即可以回避位置問題,如:
>>> def hello(greeting='hello', name='world'): ... print ("%s, %s!" % (greeting, name)) ... >>> hello(greeting="hello", name="world") hello, world! >>> hello(name="world", greeting="hello") hello, world!8.pass
pass是一個在python中不會被執行的語句,在復雜語句中,如果一個地方需要暫時被留白,它常常被用于占位符。
9.slicing
slicing是一種在有序的對象類型中(數組,元組,字符串)節選某一段的語法。
Python中的索引可以是正也可以是負。如果是正索引,0是序列中的第一個索引,1是第二個索引,如果是負索引,-1是最后一個索引,-2是倒數第二個索引。
10.字符串相關
翻轉字符串:參考Reverse a string in Python
>>> 'hello world'[::-1] 'dlrow olleh'將數字轉換成字符串:使用自帶函數str()將一個數字轉換成字符串。如果你想要八進制或者十六進制,可以用oct()或hex()。
大小寫轉換:參考Python 字符串大小寫轉換 | 菜鳥教程
>>>str = "www.runoob.com" >>>print(str.upper()) # 把所有字符中的小寫字母轉換成大寫字母 WWW.RUNOOB.COM >>>print(str.lower()) # 把所有字符中的大寫字母轉換成小寫字母 www.runoob.com >>>print(str.capitalize()) # 把第一個字母轉化為大寫字母,其余小寫 Www.runoob.com >>>print(str.title()) # 把每個單詞的第一個字母轉化為大寫,其余小寫 Www.Runoob.ComASCII碼與字符相互轉換:參考Python ASCII碼與字符相互轉換
>>>c = ‘a’ # 打印ASCII碼 >>>print (ord(c)) 97>>>a = 97 # 對應的字符 >>>print (chr(a)) a對于非ASCII碼,返回的是Unicode碼(實際上Unicode兼容了ASCII碼)。
去除字符串首尾的字符:
參考https://blog.csdn.net/qq_39208536/article/details/79267234:
>>> str = "0000000Runoob0000" >>> print (str.strip('0000000')) Runoob字符串尾部的"0000"其實是不希望截掉的,所以建議使用如下方法:
>>> print (str.replace('0000000', '')) Runoob0000判斷是否為數字或字母:
參考https://blog.csdn.net/a1007720052/article/details/81365976
>>>str.isalnum() # 所有字符都是數字或者字母(這個慎用,中文也會判斷為字母) >>>str.isalpha() # 所有字符都是字母(這個慎用,中文也會判斷為字母) >>>str.isdigit() # 所有字符都是數字 >>>str.isspace() # 所有字符都是空白字符、t、n、r官方方法還是慎用。
最好的判斷數字的方法是使用正則表達式:
import re def is_number(num):pattern = re.compile(r'^[-+]?[-0-9]d*.d*|[-+]?.?[0-9]d*$')result = pattern.match(num)if result:return Trueelse:return False>>>: is_number('1') True>>>: is_number('111') True>>>: is_number('11.1') True>>>: is_number('-11.1') True>>>: is_number('inf') False>>>: is_number('-inf') False自動給數字前面補"0":
>>>n = 123 >>>s = "%05d" % n >>>assert s == "00123"格式化字符串:參考Python格式化字符串 - 田小計劃 - 博客園
格式化操作符:%c %r %s等
格式化操作符輔助符:"-"用作左對齊,"m.n"用作“m 是顯示的最小總寬度,n 是小數點后的位數(如果可用的話)”等
字符串模板、字符串內建函數format()等也不錯。
排序:參考How to sort the letters in a string alphabetically in Python:
''.join(sorted(a))保留有效數字:參考在python中利用Formatter保留有效數字:
>>> format(12.456789, '.3g') '12.5'11.序列解包
序列解包(sequence unpacking)或遞歸解包:將多個值的序列解開,然后放到變量的序列中。它允許函數返回一個以上的值并打包成元組,然后通過一個賦值語句很容易進行訪問。所解包的序列中的元素數量必須和放置在賦值符號=左邊的變量數量完全一致,否則Python會在賦值時引發異常。如:
>>>x, y, z = 1, 2, 3 >>>print x, y, z 1 2 3 >>>score = {‘name’:’Robin’, ‘girlfriend’: “Marion’} >>>key, value = score.popitem() >>>key ‘girlfriend’ >>>value ‘Marion’12.鏈式賦值
鏈式賦值(chained assignment)是將同一個值賦給多個變量的捷徑。如:
>>>x = y = somefunction()和下面語句的效果是一樣的:
>>>y = somefunction() >>>x = y13.增量賦值
將表達式運算符(如=、-)放置在賦值運算符=的左邊。如:
>>>x = 2 >>>x += 1 >>>x 314.斷言assert
如果要確保程序中的某個條件一定為真才能讓程序正常工作的話,assert語句就有用了,它可以在程序中置入檢查點。
條件后可以添加字符串,用來解釋斷言:
>>>age = -1 >>>assert 0 < age < 100, ‘The age must be realistic’ Traceback (most recent call last):File "<stdin>", line 1, in <module> AssertionError: The age must be realistic15.with
參考淺談 Python 的 with 語句及理解Python的With語句
with語句適用于對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,比如文件使用后自動關閉、線程中鎖的自動獲取和釋放等。
with語句的語法格式為:
with context_expression [as target(s)]:with-body16.list和dict查找效率比較
參考python中in在list和dict中查找效率比較
list的查找效率遠遠低于dict的效率,原因為:
Python中list對象的存儲結構采用的是線性表,因此其查詢復雜度為O(n),而dict對象的存儲結構采用的是散列表(hash表),其在最優情況下查詢復雜度為O(1)。17.取整函數的比較
參考https://blog.csdn.net/guizaijianchic/article/details/71191807
math.ceil():向上取整,返回類型為int(與參考文章不同,是Python版本原因,在Python 2.7下驗證為float)
>>> math.ceil(2.1) 3 >>> math.ceil(2.9) 3math.floor():向下取整,返回類型為int
>>> math.floor(2.1) 2 >>> math.floor(2.9) 2round():四舍五入,返回類型為int,值得注意的點為*.5是向下取整的
>>> round(2.1) 2 >>> round(2.9) 3 >>> round(2.5) 2 >>> round(2.51) 3int():截去小數部分,返回類型為int,與math.floor()在正數時沒有差異,在負數時是有差異的(參考題 Python 3中的int()和floor()有什么區別?,詳見示例代碼)
>>> int(2.1) 2 >>> int(2.9) 2 >>> int(-2.1) -2 >>> math.floor(-2.1) -318.三元表達式(三目運算符)
參考python中的三元表達式(三目運算符) - 我是天涯邊的小白鶴 - 博客園
Python沒有與其它語言類似的三元表達式,只有類似的替代方法,如:
>>>h = “變量1” if a>b else “變量2”19.enumerate函數
參考Python enumerate() 函數:
用于將一個可遍歷的數據對象(如列表、元組或字符串)組合成一個索引序列,同時列出數據和數據下標,一般用在for循環當中:
>>>seq = [‘one’, ‘two’, ‘three’] >>>for I, element in enumerate(seq): >>> print I, element 0 one 1 two 2 three20.zip函數
參考Python3 zip() 函數:
zip() 函數用于將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的對象,這樣做的好處是節約了不少的內存。
我們可以使用 list() 轉換來輸出列表。
如果各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同,利用 * 號操作符,可以將元組解壓為列表。
>>>a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 返回一個對象 >>> zipped <zip object at 0x103abc288> >>> list(zipped) # list() 轉換為列表 [(1, 4), (2, 5), (3, 6)] >>> list(zip(a,c)) # 元素個數與最短的列表一致 [(1, 4), (2, 5), (3, 6)]>>> a1, a2 = zip(*zip(a,b)) # 與 zip 相反,zip(*) 可理解為解壓,返回二維矩陣式 >>> list(a1) [1, 2, 3] >>> list(a2) [4, 5, 6]21.將list轉為tuple
參考Convert list to tuple in Python:
>>>l = [4, 5, 6] >>>tuple(l) (4, 5, 6)22.列表推導式、字典推導式、集合推導式
參考python的各種推導式(列表推導式、字典推導式、集合推導式) - 蒼松 - 博客園
推導式(comprehensions,又稱解析式),是Python的一種獨有特性。推導式是可以從一個數據序列構建另一個新的數據序列的結構體,有列表推導式、字典推導式、集合推導式3種。
1.列表推導式
>>> multiples = [i for i in range(30) if i % 3 is 0] >>> print(multiples) [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]也可以使用()生成generator:
>>> multiples = (i for i in range(30) if i % 3 is 0) >>> print(type(multiples)) <class 'generator'>2.字典推導式
>>> mcase = {'a': 10, 'b': 34} >>> mcase_frequency = {v: k for k, v in mcase.items()} >>> print (mcase_frequency) {10: 'a', 34: 'b'}3.集合推導式
>>> squared = {x**2 for x in [1, 1, 2]} >>> print (squared) {1, 4} >>> print (type(squared)) <class 'set'>23.lambda及函數式編程
參考python函數式編程 - 蟲師 - 博客園及Python學習筆記(十二):lambda表達式與函數式編程
匿名函數lambda沒有語句的原因,是它被用于在代碼被執行的時候構建新的函數對象并且返回。lambda并不會帶來程序運行效率的提高,只會使代碼更簡潔。
lambda的一般形式是關鍵字lambda后面跟一個或多個參數,緊跟一個冒號,以后是一個表達式。如:
>>> g = lambda x,y=2,z=3 : x+y+z >>> print (g(1,z=4,y=5)) 10幾個定義好的全局函數:filter,map,reduce。這也是函數式編程的思想,優點是:
1.代碼更簡單了;
2.數據集、操作、返回值都放到了一起;
3.沒有循環體,少了些臨時變量,以及變量倒來倒去邏輯;
4.代碼變成了在描述你要干什么,而不是怎么去干;
24.讀寫文檔
參考人類身份驗證 - SegmentFault及可愛的 Python:Python中的文本處理及Python File readline() 方法及Python File(文件) 方法:
read:讀取整個文件;readline:讀取下一行,使用生成器方法;
readlines:讀取整個文件到一個迭代器以供我們遍歷;content = "" with open("test.txt", "r") as f:line = f.readline()while line:line = line.strip()print (f"line = {line}")content += lineline = f.readline()
注意最后一行是換行符,一般可以去掉。
寫文檔:
with open("test.txt", "w") as f:f.write("thresholdtfalseNegativetfalsePositiven")需要在最后加n才會換行.
w表示打開一個文件只用于寫入。如果該文件已存在則將其覆蓋。如果該文件不存在,創建新文件。
25.exec語句與eval函數
exec語句用于執行Python程序相同的方式來執行字符串,如:
>>> exec ("print ('Hello, world!')") Hello, world!eval會計算Python表達式(以字符串形式書寫),并且返回結果值。如:
>>> eval(input("Enter an arithmetric expression: ")) Enter an arithmetric expression: 6+18*2 4226.repr函數
參考Python中的repr()函數 - 波比12 - 博客園,將任意值轉換為字符串有兩種方法:傳入repr()函數或str()函數。
區別:函數str()將值轉換為適于人閱讀的形式,repr()將值轉換為供解釋器讀取的形式。
通常情況下repr()與eval()結合的對象是相同的,如:
>>> str = "I love Python" >>> str == eval(repr(str)) True >>> l = [0, 1, 2] >>> l == eval(repr(l)) True對元組是不成立的:
>>> tup = (1, 2, 3) >>> tup == eval(repr(l)) False而str()函數也要分情況判斷:
>>> s = "I love Python" >>> s == eval(str(s)) Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<string>", line 1I love Python^ SyntaxError: invalid syntax >>> l = [0, 1, 2] >>> l == eval(str(l)) True >>> tup = (1, 2, 3) >>> tup == eval(str(tup)) True27.進制等之間的轉換
參考python常用的十進制、16進制、字符串、字節串之間的轉換(長期更新帖)
10進制轉16進制: hex(16) ==> 0x10
28.any()函數
參考Python any() 函數 | 菜鳥教程
用于判斷給定的可迭代參數iterable是否全部為空對象,如果都為空、0、False,返回False,如果不都為空、0、False,則返回True。
>>> any([0, "", False]) False >>> any(['a', 'b', '', 'd']) True29.生成器
參考深入理解Python中的生成器 - Python - 伯樂在線
生成器(generator)不會把結果放在一個系列中,而是保存生成器的狀態,在每次進行迭代時返回一個值,直到遇到StopIteration異常結束。
生成器函數功能的實現依賴于yield表達式,任何包含yield語句的函數稱為生成器。生成器不像return那樣返回值,而是每次產生多個值。每次產生一個值(使用yield語句),函數就會被凍結:即函數停在那點等待被重新喚醒。函數被重新喚醒后就從停止的那點開始執行。
生成器是包含有__iter__()和__next__()方法(可參考python之__iter__函數與__next__函數)的,所以可以直接使用for來迭代,而沒有包含StopIteration的自編Iter只能通過手動循環來迭代。
五、Python庫
1.安裝
安裝單獨的包:
>>>pip install time通過requirements.txt一次性安裝大量的包:
>>>pip install -r requirements.txtrequirements.txt里每行都是一個包的名字。
安裝指定版本的包:
>>>pip install tensorflow-gpu==1.9.0如果出現如下報錯:
Permission denied: '/home/dao/anaconda2/lib/python2.7/site-packages/easy-install.pth'問題在于安裝權限不夠,將anaconda2的用戶所有者由root改為自己的用戶名即可:
sudo chown -R ‘a’ /home/a/anaconda22.單元測試unittest
參考單元測試
在Python中,unittest是Python中的單元測試框架。它擁有支持共享搭建、自動測試、在測試中暫停代碼、將不同測試迭代成一組,等等的功能。
測試類需要從unittest.TestCase繼承,測試方法需要以test開頭。
一種常見的運行方法是:
>>>python -m unittest mydict_test -m mod : run library module as a script (terminates option list)參考python自動化-unittest批量執行用例(discover) - anlcy - 博客園,可以使用unittest模塊中的TestLoader類中的discover方法來批量執行用例。
一個典型的用法是:
>>>python -m unittest discover -p '*_test.py' -case_dir:這個是待執行用例的目錄。 -pattern[-p]:這個是匹配腳本名稱的規則,test*.py意思是匹配test開頭的所有腳本。 -top_level_dir:這個是頂層目錄的名稱,一般默認等于None就行了。3.唯一ID生成庫UUID
參考Python使用UUID庫生成唯一ID - dkcndk - 博客園
UUID是128位的全局唯一標識符,通常由32字節的字符串表示。可以保證時間和空間的唯一性,也稱為GUID。
它通過MAC地址、時間戳、命名空間、隨機數、偽隨機數來保證生成ID的唯一性。
UUID主要有五個算法,使用方面:
1.Python中沒有基于DCE的,所以uuid2可以忽略;
2.uuid4存在概率性重復,由無映射性,最好不用;
3.若在Global的分布式計算環境下,最好用uuid1;
4.若有名字的唯一性要求,最好用uuid3或uuid5。
>>>import uuid >>>print(str(uuid.uuid4())) 9c0786a4-619e-4c07-9862-0409200437d34.pickle
安裝參考How to install cPickle on Python 3.4?:
import _pickle as cPicklePython 3找不到cPickle可參考python錯誤之ImportError: No module named 'cPickle'::
將cPickle改為pickle即可5.Flask
入門文檔可參考Tutorial - Flask 1.0.2 documentation
獲取訪問者的IP地址可參考使用Python Flask獲取訪問者的IP地址 - 代碼日志:
>>>from flask import request >>>from flask import jsonify>>>@app.route("/get_my_ip", methods=["GET"]) >>>def get_my_ip(): >>> return jsonify({'ip': request.remote_addr}), 200參考How to prevent Unicode representation for Latin1 characters?及Flask設置返回json格式數據 - Penguin及人類身份驗證 - SegmentFault
使用Python官方的jsonify模塊有可能會出錯,沒有正確使用UTF-8去傳輸中文數據:
return jsonify(code=1000, message=decodeText, decodeType=decodeType)可以使用json代替:
return json.dumps({"code":1000, "message":decodeText, "decodeType":decodeType}, ensure_ascii=False)一個實例就是應該返回的是't這',而得到的是'tè??',遺憾的這個轉換怎么來的我還沒有能力推導,一個思路是:
>>> u"這".encode("utf-8") b'xe8xbfx99' >>> hex(ord("è")) '0xe8' >>> hex(ord("?")) '0xbf' >>> hex(ord("?")) '0x2122'但是這個依然是有問題的,別人測試我代碼是在Windows系統中測試的,里面的默認編碼是GBK而不是UTF-8,所以還是需要指定好。
參考不要相信requests編碼后返回的text - 猿人學Python及Python HTTP庫requests中文頁面亂碼解決方案!,其編碼頭(在Python中打印可以參考python 調試 requests 打印 HTTP 請求與響應)一般是這樣的:
Content-Type: text/html而不是:
Content-Type: text/html; charset=utf-8所以會使用默認的GBK進行解碼,而不是想象中的UTF-8。
另外一個問題就是最好使用"application/json"而不是"text/html"設計編碼頭,這個可以參考What does "Content-type: application/json; charset=utf-8" really mean?及https://stackoverflow.com/questions/477816/what-is-the-correct-json-content-typeWhat is the correct JSON content type?。
在Python的設置可以參考Forcing application/json MIME type in a view (Flask)及Python Flask, how to set content type:
import json from flask import Response ret = json.dumps({"code":1010, "message":”hello, world!"}, ensure_ascii=False) return Response(response=ret, status=200, mimetype="application/json; charset=utf-8")6.os
獲取文件路徑:參考記錄下os.path.dirname(__file__)使用:
import os print (os.path.dirname(__file__))一般來說返回的是相對路徑,所以最好先求絕對路徑:
import os print (os.path.dirname(os.path.abspath(__file__)))統計文件夾內文件個數:參考python (9)統計文件夾下的所有文件夾數目、統計文件夾下所有文件數目、遍歷文件夾下的文件
統計以.jpg結尾的文件個數:
>>>import os >>>len([i for i in os.listdir(“./”) if i.split(".")[-1] == "jpg"])判斷文件和文件夾是否存在:參考python 判斷路徑是文件還是文件夾、判斷是否存在、獲取文件大小
import os if os.path.isdir(path):print "it's a directory" elif os.path.isfile(path):print "it's a normal file" else:print "it's a special file(socket,FIFO,device file)"獲取文件夾下所有文件:參考Python獲取文件夾下的文件和子文件夾,os.walk()函數執行之后得到一個三元tupple(dirpath, dirnames, filenams),os.listdir()函數返回指定路徑下的文件和文件夾列表。
創建文件夾:參考python創建文件和文件夾:
>>>os.makedirs("/root/tmp")重命名:參考How to move a file in Python:
os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")客觀上,改變文件路徑也可以起到移動文件的效果。
7.讀寫excel庫xlrd
參考python操作Excel讀寫--使用xlrd - lhj588 - 博客園
打開文件:
import xlrd # read the sheet try:data = xlrd.open_workbook(os.path.join(cfg.DATA_FOLDER, name)) except Exception, e:print str(e)table = data.sheets()[6]讀取目標行列值:
print (table.cell(i, 4).value)表示讀取第i行、第4列的值,注意index從0開始。
8.platform
獲取平臺名稱:參考Python判斷當前操作系統類型以及os/sys/platform模塊簡介:
>>>import platform >>>platform.node() ‘a’9.sys
獲取系統目錄:sys.path,返回一個列表:
['',..., '/home/a/anaconda2/envs/python36/lib/python3.6/site-packages']該列表可修改,參考python 在不同層級目錄import 模塊的方法,可通過往系統目錄插入需求目錄的方法改變Python解釋器的入口:
this_dir = os.path.dirname(__file__) sys.path.append(this_dir + '/..')10.XML解析庫xml.etree.ElementTree
參考Python XML 解析 | 菜鳥教程,XML指可擴展標記語言(eXtensible Markup Language).XML被設計用來傳輸和存儲數據.XML是一套定義語義標記的規則,這些標記將文檔分成許多部件加以標識.它也是元標記語言,即定義了用于定義其他與特定領域有關的,語義的,結構化的標記語言的句法語言。
參考用 ElementTree 在 Python 中解析 XML,可使用xml.etree.ElementTree來解析xml。官方文檔在19.7. xml.etree.ElementTree - The ElementTree XML API - Python 2.7.16 documentation。
可能有用的文章Python xml屬性/節點/文本的增刪改[xml.etree.ElementTree]及深入解讀Python解析XML的幾種方式| 編程派 | Coding Python。
11.matplotlib
基本方法可參考python 畫圖--簡單開始及折線圖,繪制文字可參考四、Matplotlib系列---pyplot的文本顯示,繪制散點圖可參考使用Matplotlib繪制散點圖 | 爛筆頭,繪制圖例說明可參考matplotlib.pyplot.legend - Matplotlib 3.1.0 documentation,設置坐標軸范圍可參考【Matplotlib】線設置,坐標顯示范圍 - Chris*Chen - 博客園。
如果報錯:
QXcbConnection: Could not connect to display參考https://www.douban.com/note/612063589/,原因在于無界面操作的Linux系統不能在界面里畫圖,所以需要隱藏該操作,改show為save,將圖片保存下來,轉到有界面的操作系統里觀看。
在import matplotlib.pyplot as plt前添加引用:
import matplotlib matplotlib.use('Agg')12.PyTorch
在PyTorch下載依賴包,安裝,再安裝torchvision:
pip install torchvision13.FontTool
一個應用在Michael:解決了困擾了一個禮拜的一個坑,只在Windows下可以使用的一個字體終于可以在Linux下使用了,源代碼在fontTools/ttLib/ttFont.py。
14.logging
參考python logging模塊使用教程:
15.base64
本地圖片轉base64格式:
import base64 with open(imgPath, 'rb') as f:rawContent = f.read()imgBase64 = base64.b64encode(rawContent)base64格式轉numpy格式:
imgData = base64.b64decode(dataInput) imgData = np.fromstring(imgData, np.uint8) print (imgData.shape) # (94180,) imgArr = cv2.imdecode(imgData, cv2.IMREAD_COLOR) print (imgArr.shape) # (816, 610, 3)如果報錯:TypeError: Incorrect padding,參考python base64解碼TypeError: Incorrect padding錯誤及http://www.phperz.com/article/15/1002/45577.html,對base64解碼的string補齊等號就可以了:
def decode_base64(data):"""Decode base64, padding being optional.:param data: Base64 data as an ASCII byte string:returns: The decoded byte string."""missing_padding = 4 - len(data) % 4if missing_padding:data += b'='* missing_paddingreturn base64.decodestring(data)OpenCV轉base64,參考python PIL/cv2/base64相互轉換及OpenCV-Python cv2.imdecode()和cv2.imencode() 圖片解碼和編碼:
# encode the image base64_str = cv2.imencode('.png', thumbnail)[1].tostring() jsImg = base64.b64encode(base64_str)16.數據讀寫庫json與pickle
參考在Python里創建JSON文件及讀寫保存JSON數據及PYTHON將list或/dict對象寫入txt/json文件
寫文件:
jsonDictResult = json.dumps(dictResult, ensure_ascii=False) with open(os.path.join('data', 'result.json'), 'w') as f:f.write(jsonDictResult)讀文件:
with open("result.json", "r") as f:dictResult = json.load(f)另一個相似的庫是Pickle,參考What is Pickle in python ?及Understanding Python Pickling with example - GeeksforGeeks。pickle模塊可以讀入任何Python對象,將它們轉換成字符串,然后使用dump函數將其存儲到一個文件中——這個過程叫做pickling。反之,從存儲的字符串文件中提取原始Python對象的過程,叫做unpickling。
# pickling >>> a = {"h":1, "e":2} >>> import pickle >>> with open("a.log", "wb") as f: ... pickle.dump(a, f)# unpicling >>> with open("a.log", "rb") as f: ... b = pickle.load(f) >>> b {'h': 1, 'e': 2}json與pickle幾點不一樣的地方:
17.requests
參考Python 使用requests發送POST請求及快速上手 - Requests 2.18.1 文檔
HTTP協議規定post提交的數據必須放在消息主體中,但是協議并沒有規定必須使用什么編碼方式。服務端通過請求頭中的Content-Type字段來獲知請求中的消息主體是用何種方式進行編碼,再對消息主體進行解析。
具體的編碼方式包括:
1.application/x-www-form-urlencoded。最常見的post提交數據的方式,以form表單形式提交數據;
只需要將請求的參數構造成一個字典,然后傳給requests.post()的data參數即可:
url = 'http://httpbin.org/post' d = {'key1': 'value1', 'key2': 'value2'} r = requests.post(url, data=d) print (r.text)2.application/json。以json串提交數據;
rl = 'http://httpbin.org/post' s = json.dumps({'key1': 'value1', 'key2': 'value2'}) r = requests.post(url, data=s) print (r.text)3.multipart/form-data。一般使用來上傳文件;
url = 'http://httpbin.org/post' files = {'file': open('report.txt', 'rb')} r = requests.post(url, files=files) print (r.text)18.CharlesShang/TFFRCNN
報錯:
tensorflow.python.framework.errors_impl.NotFoundError: ./faster_rcnn/../lib/roi_pooling_layer/roi_pooling.so: undefined symbol: _ZTIN10tensorflow8OpKernelE參考Undefined symbol: _ZTIN10tensorflow8OpKernelE · Issue #108 · CharlesShang/TFFRCNN,需要加上:
-L $TF_LIB -ltensorflow_framework報錯:
RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). max_open_warning, RuntimeWarning)參考warning about too many open figures:
import matplotlib.pyplot as plt plt.rcParams.update({'figure.max_open_warning': 0})報錯:
you may need to pass the encoding= option to numpy.load參考python3中的np.load編碼問題,原因在于在Python2 中的默認編碼為ASCII,但是在Python3中的默認編碼為UTF-8。 需要指定編碼格式為ASCII,使用下列指令:
np.load(det.npy, encoding="latin1")19.attention_ocr
報錯:
str' object has no attribute 'decode'.參考'str' object has no attribute 'decode'. Python 3 error?:
You are trying to decode an object that is already decoded. You have a str, there is no need to decode from UTF-8 anymore.Simply drop the .decode('utf-8') part.
報錯:
AttributeError: type object '_io.StringIO' has no attribute 'StringIO'參考AttributeError: type object '_io.StringIO' has no attribute 'StringIO' · Issue #111 · pgbovine/OnlinePythonTutor:
try:from io import StringIO except:import StringIO保存圖片可以這樣:
io = BytesIO() image_pil = PILImage.fromarray(image) image_pil.save(io, image_format, subsampling=0, quality=100)一個相關的博客StringIO和BytesIO。
20.faiss
安裝很簡單:
pip install faiss運行報錯:
ImportError: libopenblas.so.0: cannot open shared object file: No such file or directory參考Scipy installation issue, getting ImportError: libopenblas.so.0: cannot open shared object file or directory:
sudo apt-get install libopenblas-dev運行報錯:
ImportError: libomp.so: cannot open shared object file: No such file or directory參考ImportError: No module named '_swigfaiss · Issue #821 · facebookresearch/faiss:
sudo apt-get install libomp-dev在Centor中安裝可參考llvm-toolset-7-libomp-5.0.1-2.el7.x86_64.rpm CentOS 7 Download:
yum install centos-release-scl-rh yum install llvm-toolset-7-libomp需要將庫放到環境變量下:
export LD_LIBRARY_PATH="/opt/rh/llvm-toolset-7/root/usr/lib64/:$LD_LIBRARY_PATH"六、類
1.基本概念
參考Python 面向對象 | 菜鳥教程
類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。類變量:類變量在整個實例化的對象中是公用的。類變量定義在類中且在函數體之外。類變量通常不作為實例變量使用。數據成員:類變量或者實例變量, 用于處理類及其實例對象的相關的數據。方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱為方法的重寫。局部變量:定義在方法中的變量,只作用于當前實例的類。實例變量:在類的聲明中,屬性是用變量來表示的。這種變量就稱為實例變量,是在類聲明的內部但是在類的其他成員方法之外聲明的。繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個派生類的對象作為一個基類對象對待。例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關系(例圖,Dog是一個Animal)。實例化:創建一個類的實例,類的具體對象。方法:類中定義的函數。對象:通過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。我認為主要要弄明白的概念是類和對象的區別。
2.基本應用
舉例:
#!/usr/bin/python # -*- coding: UTF-8 -*-class Employee:'所有員工的基類'empCount = 0def __init__(self, name, salary):self.name = nameself.salary = salaryEmployee.empCount += 1def displayCount(self):print ("Total Employee %d" % Employee.empCount)def displayEmployee(self):print ("Name : ", self.name, ", Salary: ", self.salary)empCount 變量是一個類變量,它的值將在這個類的所有實例之間共享。你可以在內部類或外部類使用 Employee.empCount 訪問。第一種方法__init__()方法是一種特殊的方法,被稱為類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法
self 代表類的實例,self 在定義類的方法時是必須有的,雖然在調用時不必傳入相應的參數。
可以使用以下函數的方式來訪問屬性:
getattr(obj, name[, default]) : 訪問對象的屬性。hasattr(obj,name) : 檢查是否存在一個屬性。
setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,會創建一個新屬性。
delattr(obj, name) : 刪除屬性。
對Python的固有類型int等也可以通過上述方法去訪問其屬性。
Python 對象的實例化過程及[深入Python]__new__和__init__ - 鴣斑兔 - 博客園介紹了除__init__外的另一種構造方法__new__。
3.元類metaclass
參考python 類和元類(metaclass)的理解和簡單運用及深刻理解Python中的元類(metaclass) - 文章 - 伯樂在線及使用元類
元類就是創建類的類。函數type實際上就是一個元類,type就是Python在背后用來創建所有類的元類。如:
>>>age = 35 >>>age.__class__ <type ‘int’> >>>age.__class__.__class__ <type ‘type’> >>>def foo(): pass >>>foo.__class__ <type ‘function’> >>>foo.__class__.__class__ <type ‘type’>4.裝飾器
參考[轉載]python中的@符號的作用_程序猿妞妞妞_新浪博客及PEP 318 -- Decorators for Functions and Methods
一個修飾符就是一個函數,它就被修飾的函數作為參數,并返回修飾后的同名參數或其它可調用的東西。
要想使被修飾函數能正常運行,必須加返回值,@decorator是一個statement,會將被修飾函數當作參數傳入來執行:
>>> def decorator(fn): ... def test(*args): ... print ("My god!"*3) ... return fn(*args) ... return test ... >>> @decorator ... def other(a, b)File "<stdin>", line 2def other(a, b)^ SyntaxError: invalid syntax >>> def other(a, b): ... print (a**2+b**2) ... >>> other(4, 3) 25參考Python裝飾器 - 田小計劃 - 博客園,裝飾器是可以疊加使用的,那么這是就涉及到裝飾器調用順序了。對于Python中的"@"語法糖,裝飾器的調用順序與使用 @ 語法糖聲明的順序相反。
裝飾器本身也可以支持參數,如:@demo(False)。
在Python中有三個內置的裝飾器,都是跟class相關的:@staticmethod、@classmethod和@property。
1.@staticmethod是類靜態方法,其跟成員方法的區別是沒有self參數,并且可以在類不進行實例化的情況下調用。@staticmethod是把函數嵌入到類中的一種方式,函數就屬于類,同時表明函數不需要訪問這個類。通過子類的繼承覆蓋,能更好的組織代碼;
參考飄逸的python - @staticmethod和@classmethod的作用與區別,類靜態方法調用自身不是使用self.static_foo()函數,而是使用A.static_foo()函數。
2.@classmethod與成員方法的區別在于所接收的第一個參數不是self(類實例的指針),而是cls(當前類的具體類型)。@classmethod因為持有cls參數,可以來調用類的屬性,類的方法,實例化對象等,避免硬編碼;
@classmethod與@staticmethod之間的區別可以參考python中@classmethod @staticmethod區別及Python 中的 classmethod 和 staticmethod 有什么具體用途?。
3.@property是屬性的意思,表示可以通過類實例直接訪問的消息。可以將返回變量設為只讀,防止修改變量引發的問題;
可以參考使用@property。
參考How to strip decorators from a function in Python,如果想調用未帶裝飾器的函數,可以這樣:
def with_connection(f):def decorated(*args, **kwargs):f(get_connection(...), *args, **kwargs)decorated._original = freturn decorated @with_connection def spam(connection):# Do something spam._original(testcon) # calls the undecorated function作用就是在修飾符函數中定義被修飾函數。
5.abc
參考abc - Abstract Base Classes - Python 3.7.3 documentation及abc — 抽象類別 — 你所不知道的 Python 標準函式庫用法 03 | louie_lu's blog
使用 Python abc 套件的原因,是為了要解決 Python 沒有「抽象類別 (abstract class)」的問題。透過抽象類別,我們可以建立一個比起使用 hasattr() 還要更嚴格的類別介面 (class interface) 檢查。
6.多態
參考繼承和多態及再談python中的多態
對象最重要的優點包括:
1.多態(Polymorphism)。意味著可以對不同類的對象使用同樣的操作,它們會像被“施了魔法一般”工作;
2.繼承(Inheritance)。以通用的類為基礎建立專門的類對象;
3.封裝(Encapsulation)。對外部世界隱藏對象的工作細節。
7.__str__
參考python: 理解__str__
當打印一個類的時候,print首先調用的就是類里面的的定義的__str__。
一些可能有用的網址:Are functions objects in Python?
python類的繼承 - Bigberg - 博客園
Python super() 函數
Python 面向對象 | 菜鳥教程
七、Python語言
1.什么是Python?使用Python有什么好處?
Python是一種編程語言,它有對象、模塊、線程、異常處理和自動內存管理。
Python簡潔、簡單、方便、容易擴展,有許多自帶的數據結構,而且Python開源。
Python是一種解釋型語言,Python代碼在運行之前不需要編譯,源代碼可以直接運行,Python解釋器會將源代碼轉換成中間語言,之后再翻譯成機器碼再執行。其他解釋型語言還包括PHP和Ruby。
Python是動態類型語言,動態語言指的是一類在運行時可以改變其結構的語言,即在聲明變量時,不需要說明變量的類型,動態語言能動態給實例綁定屬性。
Python非常適合面向對象的編程(OOP),因為它支持通過組合與繼承的方式定義類。Python中的類沒有訪問說明符(類似C++中的public和private)。
Python代碼編寫快,因此程序員可以專注于算法和數據結構的設計,而不用處理底層的細節。
2.PEP8 Python編程規范
參考PEP8 Python 編碼規范整理,PEP8是一個編程規范,內容是一些關于如何讓你的程序更具可讀性的建議,比如縮進使用4個空格而不是Tab鍵。
3.管理內存
Python作為一種動態語言,其變量和對象是分離的,關于此部分的介紹可以參考Michael:[Python]可變對象與多進程。對象存在于內存之中,Python采用引用計數的垃圾回收機制來釋放內存。
Python的內存管理是由私有heap空間管理的,所有的Python對象和數據結構都在一個私有的heap中。只有解釋器才有訪問heap的權限,而為heap空間分配內存是由Python的內存管理模塊負責的,其核心API會提高一些接口供外部訪問(比如gc.collect()可以手動回收內存)。
參考簡單理解python下的變量和內存,Python是有小整數對象池和大整數對象池概念的,Python 對小整數的定義是[-5, 256],這些整數對象是提前建立好的,不會被垃圾回收,可以做這么一個實驗:
>>> id(4) 93991663884928 >>> id(5) 93991663884960 >>> id(6) 93991663884992 >>> x = 4 >>> id(x) 93991663884928 >>> x = 5 >>> id(x) 93991663884960 >>> x = 6 >>> id(x) 93991663884992內存的分配也是跟解釋器相關的,個人猜測是建立解釋器的時候就會申請一批內存給小整數對象池。
參考Python深入06 Python的內存管理,其它不可變對象中對其所有的引用都是指向同一對象的:
>>> a = "good" >>> b = "good" >>> id(a) 140479393598744 >>> id(b) 140479393598744 >>> a is b True垃圾回收機制依賴引用計數,對每個對象,解釋器都會記錄指向該對象的引用總數,稱為引用計數(reference count)。可以使用sys庫中的getrefcount()函數來查看某個對象的引用計數。值得注意的是,在調用getrefcount()的過程中,因為傳參也相當于在函數體局部命名空間創建了一個指向該對象的變量,因此該函數所得到的結果會比期望的多1:
>>> import sys >>> a = [1, 2, 3] >>> sys.getrefcount(a) 2 >>> b = a >>> sys.getrefcount(a) 3可以使用del()語句來刪除某個引用,也可以用于刪除容器元素中的元素,因為容器內的元素也只是對象的應用:
>>> import sys >>> sys.getrefcount(1) 765 >>> a = 1 >>> sys.getrefcount(1) 766 >>> b = [a] >>> sys.getrefcount(1) 767 >>> del(b[0]) >>> sys.getrefcount(1) 766Python在運行時,會記錄其中分配對象(object allocation)和取消分配對象(object deallocation)的次數,當兩者的數值高于某個閾值時,垃圾回收才會啟動。
可以通過gc模塊的get_threshold()方法來查看該閾值:
>>> import gc >>> gc.get_threshold() (700, 10, 10)可以看到一共有三個數,第一個數700表示的是垃圾回收啟動的閾值,可以通過gc.set_threshold()方法重新設置閾值,后兩個數代表的是Python分代(generation)回收的策略。這一策略的基本假設是:存活時間越久的對象,越不可能變為垃圾對象。因此,Python將所有的對象分為0、1、2三代。所有的新建對象都是0代對象,當某一代對象經歷過垃圾回收,依然存活,那么它就被歸入下一代對象。上述的(700, 10, 10)就表示每10次0代的垃圾回收,會配合1次1代的垃圾回收,而每10次1代的垃圾回收,才會有1次2代的垃圾回收。
也可以手動啟動垃圾回收,即使用gc.collect():
>>> a = "hello" >>> id("hello") 140701853023568 >>> del(a) >>> id("hello") 140701853023568 >>> import gc >>> gc.collect() 0 >>> id("hello") 140701853500672 >>> id("hello") 140701853500672可以看到,通過del(a)刪掉"hello"的引用后,"hello"依然存在于內存之中,且通過id可以知道是之前分配的內存,手動回收之后發現id已經變化,表示已經消除了"hello",只是在提取id的過程中重新分配了內存。
引用環的意思是兩個對象相互引用,從而構成了一個引用的環,比如:
>>> import sys >>> a = [] >>> sys.getrefcount(a) 2 >>> b = [a] >>> sys.getrefcount(a) 3 >>> sys.getrefcount(b) 2 >>> a.append(b) >>> a [[[...]]] >>> sys.getrefcount(a) 4 >>> sys.getrefcount(b) 3可以看到,a.append(b)后就構成了一個引用環,然后,a和b的引用都增加了1,這個現象也是非常的有趣。
可以看到,就算把引用a,b都刪掉了,兩個對象的引用計數也沒有降到0,因此不會被垃圾回收。為了回收這樣的引用環,Python復制每個對象的引用計數,可以記為gc_ref。對于每個對象i引用的對象j,將相應的gc_ref_j減1。在結束遍歷后,gc_ref不為0的對象,和這樣對象引用的對象,以及繼續更下游的對象,需要被保留,而其它的對象則被垃圾回收。
我理解的解決策略是不僅僅記錄對象被引用的次數,還記錄引用的次數,而環則表示相互引用、相互被引用,非環狀引用則沒有這個問題。
如何釋放Python占用的內存?里面有些不錯的內容,有時間可以看看。
4.靜態分析
PyChecker是一個靜態分析工具,它不僅能報告源代碼中的錯誤,并且會報告錯誤類型和復雜度。Pylint是檢驗模塊是否達到代碼標準的另一個工具。
5.Python的編譯機制
參考Python學習筆記之二——Python的運行機制及談談 Python 程序的運行原理
解釋器是一種讓其它程序運行起來的程序,它是代碼與機器的計算機硬件之間的軟件邏輯層,Python解釋器是能夠讓Python程序在機器上執行的一套程序。
Python解釋器執行的步驟:
1.將原始代碼編譯成字節碼對象
在運行期間,編譯結果是字節碼對象PyCodeObject,只存在于內存中,是特定于Python的一種表現形式,它不是二進制的機器碼,需要進一步編譯才能被機器執行;而該模塊執行完后,編譯結果保存到了.pyc文件中,這樣下次就不用編譯,直接加載到內存中,因此,.pyc文件是PyCodeObject對象在硬盤上的表現形式。
PyCodeObject對象包含了Python源代碼中的字符串、常量值以及通過語法解析后編譯生成的字節碼指令。PyCodeObject對象還會存儲這些字節碼指令與原始代碼行號的對應關系,這樣當出現異常時,就能指明位于哪一行的代碼。
.pyc文件包含了三部分信息:Python的magic number、.pyc文件創建的時間信息以及PyCodeObject對象。
2.將編譯好的字節碼對象轉發到Python虛擬機(Python Virtual Machine, PVM)中進行執行
PVM是Python的運行引擎,是Python系統的一部分,它是迭代運行字節碼指令的一個大循環,一個接一個地完成操作。
Python解釋器有三種主要的實現方式:
1.CPython
CPython是標準的實現,是用C語言編寫的,是大多數Linux和Mac OS X機器預裝的Python解釋器,也是所有Python解釋器中運行最快、最完整、最健全的。
2.Jython
設計的目的是為了與Java編程語言繼承,Jython要比CPython慢,而且也不夠健壯,它往往看作是一個主要面向尋找Java代碼前端腳本語言的Java開發者的一個有趣的工具。
3.IronPython
設計的目的是讓Python程序可以與Windows平臺上的.NET框架以及與之對應的Linux上的開源的Mono編寫成的應用集成。
參考談談 Python 程序的運行原理,Python通過一個全局解釋器鎖GIL(Global Interpreter Lock)來實現線程同步的,線程調度機制會為線程分配GIL,獲取到GIL的線程就能開始執行,而其它線程則必須等待。由于GIL的存在,Python的多線程性能十分低下,無法發揮多核GPU的優勢,性能甚至不如單線程。因此如果想用多核GPU,一個建議是使用多進程。
6.內存泄露問題
參考如何解決Python2的內存泄漏問題 - 程序園
pymalloc在一輪暴虐之后進程內存下不去。
不使用pymalloc容易導致不少兼容性的問題出現,而且許多python的新feature會用不了,不建議這么做。
而tcmalloc果然名不虛傳,run方法結束后,內存馬上釋放到解放前。建議生產環境嘗試使用tcmalloc編譯的Python解釋器,其它兼容性的問題有待考證。
C++上的安裝可參考tcmalloc安裝與使用。
其它可參考的文章:內存優化總結:ptmalloc、tcmalloc和jemalloc、白山云科技:Python 進程內存增長解決方案。
7.Python 2.x和Python 3.x的區別
參考Python3.x和Python2.x的區別 - 紫紅的淚 - 博客園
這里摘抄幾條比較重要的:
1.Python 3運行較慢,大概15%到30%;2.Python 3默認使用UTF-8編碼;
3.去除print語句,加入print()函數實現相同的功能;
4.整型除法返回浮點數,要得到整型結果,請使用//;
5.捕獲異常的語法改變,引入了as關鍵字來標識異常實例,即except NotImplementedError as error;
6.去除了xrange(),range()返回的一個迭代器,而不是列表;
8.單下劃線和雙下劃線
參考http://python.jobbole.com/81129/及python 里面的單下劃線與雙下劃線的區別(私有和保護)
單下劃線:會在以下三種場景中使用:
1.在解釋器中:_代表交互式解釋器回話中上一條執行的語句的結果;
2.作為一個名稱:_作為臨時性的名稱使用,如:for _ in range(10);
3.國際化:作為一個函數來使用,_通常用于實現國際化和本地化字符串之間翻譯查找的函數名稱,源自并遵循相應的C約定,如output = _(“Welcome to my site.”);
另外,使用名稱前的單下劃線,用于制定該屬性為“私有”,在模塊或類外不可以使用。
名稱前的雙下劃線:為了避免與子類定義的名稱沖突,__spam這種形式(至少兩個前導下劃線,最多一個后續下劃線)的任何標識符將會被__classname__spam這種形式取代。另外,表示的是私有類型的變量,只能允許這個類本身進行訪問,連子類也不可以;
名稱前后的雙下劃線:為了確保不會與用戶自定義的名稱沖突,如__init__;
9.GIL線程全局鎖
參考Python的GIL是什么鬼,多線程性能究竟如何及python GIL 全局鎖
GIL(Global Interpreter Lock,全局鎖)是一個防止多線程并發執行機器碼的一個Mutex。
GIL不是Python的特性,是實現Python解析器CPython時所引入的一個概念,Python完全可以不依賴于GIL。
Python的多線程在多核CPU上,只對于IO密集型計算產生正面效果;而當有至少有一個CPU密集型線程存在,那么多線程效率會由于GIL而大幅下降。
解決方法:
1.用multiprocessing替代thread;
2.用其它解析器;
協程可參考協程:協程,又稱微線程,纖程,英文名Coroutine。
優勢:
1.極高的執行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯;2.不需要多線程的鎖機制,因為只有一個線程,也不存在同時寫變量沖突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多;
10.sys.stdout
參考Python 標準輸出 sys.stdout 重定向
Python打印對象事實上是調用了sys.stdout.write(obj+'n')。
因此,可以從控制臺重定向到文件:
>>> import sys >>> sys.stdout=open('out.log', 'w') >>> print ("hello")sys.stdout.flush()可以參考sys.stdout.flush()在Linux和Windows系統下的作用-YHT的運維筆記-51CTO博客,但我實驗顯示沒有加該指令刷新也很及時。
另外分享一個很不錯的打印方法:
print (f"content = {content}")11.Python3的bytes/str之別
Unicode與UTF-8之間的關系可以參考Unicode 和 UTF-8 有什么區別?:
Unicode:字符集,全名為Universal Multiple-Octet Coded Character Set,簡稱“UCS",為每一個字符分配一個唯一的ID(學名為碼位/碼點/Code Point);UTF-8:編碼規則,全名為UCS Transfer Format-8,將碼位轉換為字節序列的規則,是一套以8位為一個編碼單位的可變長編碼,會將一個碼位編碼為1到4個字節;
在Python里可以這樣求解:
>>> a = u"知" >>> hex(ord(a)) '0x77e5' >>> a.encode("utf-8") b'xe7x9fxa5'可以看到與上圖是對應的。
參考Python 3的bytes/str之別,Python 3中,對文本和二進制數據做了更為清晰的區分,文本總是Unicode,由str類型表示,二進制數據則由bytes類型表示。
字符串是文本的抽象表示,字符串由字符組成,字符則是與任何特定二進制表示無關的抽象實體。
參考Python對中文字符的處理(utf-8/ gbk/ unicode),對各種中文編碼方式的轉換可以依賴中間值unicode編碼(即上圖的string):
s.decode('utf-8').encode('gbk')該句子的意思即為將utf-8編碼轉為gbk編碼。
如果報錯:
UnicodeEncodeError: 'ascii' codec can't encode character u'u5e74' in position 26: ordinal not in range(128)參考UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position 20: ordinal not in range(128)
如果不能保存中文即utf-8字符,需要將ASCII字符轉碼成utf-8字符:
>>>cv2.imwrite(os.path.join(“/root", "%s.png" % dateName.encode('utf-8')), img)Python2中關于UTF-8的寫法可參考python2編碼總結 - 晉好林 - 博客園及[Python]編碼聲明:是coding:utf-8還是coding=utf-8呢。
12.模塊和包
一個包含多個Python代碼的文件夾是一個包,一個包可以包含模塊和子文件夾。
模塊是搭建程序的一種方式,每一個Python代碼文件都是一個模塊。模塊的真正用處在于可以像類一樣保持自己的作用域,這意味著定義的 所有類和函數以及賦值后的變量都稱為了模塊的特性。
導入模塊需要告知編譯器模塊位置,求解編譯器模塊位置:
>>> import sys >>> print (sys.path) ['', '/home/dao/anaconda2/envs/python36/lib/python36.zip', '/home/dao/anaconda2/envs/python36/lib/python3.6', '/home/dao/anaconda2/envs/python36/lib/python3.6/lib-dynload', '/home/dao/anaconda2/envs/python36/lib/python3.6/site-packages']sys.path是一個可修改列表,在本文5.9節介紹了在Python環境下改變Python路徑的方法。
在Linux環境下增加Python路徑的方法:
export PYTHONPATH=$PYTHONPATH:~/python通過字符串名導入模塊的方法可參考10.10 通過字符串名導入模塊:
import importlib configLib = importlib.import_module("lib.config%s" % args.element) cfg = configLib.cfg參考Python包的相對導入時出現“ ‘Parent module ' not loaded, cannot perform relative import”的解決方法_python_何問起,文件夾被Python解釋器視為包需要滿足兩個條件:
1.文件夾中必須有__init__.py文件,該文件夾可以為空,但必須存在該文件;2.不能作為頂層模塊來執行該文件夾中的.py文件(即不能作為主函數的入口);
所以,引用同一目錄下的文件使用from . import xxx可能會有這樣的兩個錯誤:
SystemError: Parent module '' not loaded, cannot perform relative import ValueError: attempted relative import beyond top-level package參考SystemError: Parent module '' not loaded, cannot perform relative import,可以這樣解決:
try:from .mymodule import myclass except Exception: #ImportErrorfrom mymodule import myclass13.異常
參考8. Errors and Exceptions
Python用異常對象(exception object)來表示異常情況。遇到錯誤后,會引發異常。如果異常對象并未被處理或捕捉,程序就會用所謂的回溯(traceback,一種錯誤信息)終止執行。
處理異常可以使用try/except語句來實現,重新引發可以調用不帶參數的raise.
示例:
>>> def divide(x, y): ... try: ... result = x / y ... except ZeroDivisionError: ... print("division by zero!") ... else: ... print("result is", result) ... finally: ... print("executing finally clause") ... >>> divide(2, 1) result is 2.0 executing finally clause >>> divide(2, 0) division by zero! executing finally clause >>> divide("2", "1") executing finally clause Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'捕捉所有異常是危險的,因為它會隱藏所有程序員未想到并且未做好準備處理的錯誤。它同樣會捕捉用戶終止執行的Crtl+C企圖,以及用sys.exit函數終止程序的企圖,等等。這時用except Exception, e會更好些,或者對異常對象e進行一些檢查。
14.猴子補丁
“猴子補丁”指的是在函數或對象已經對弈之后,再去改變它們的行為。
15.單例模式
參考單例模式_百度百科及[python實現設計模式]-1. 單例模式 - abstract未央 - 博客園
單例模式是一種常用的軟件設計模式,在它的核心結構中只包含一個被稱為單例的特殊類,通過單例模式可以保證系統中一個類只有一個實例。對于系統中的某些類來說,只有一個實例很重要,例如,一個系統可以存在多個打印任務,但是只能有一個正在工作的任務。
16.字典的內部實現
參考Python dictionary implementation,中文翻譯為深入 Python 字典的內部實現 - Python - 伯樂在線。
17.內置算法的復雜度
參考python中各種結構的復雜度 - mrbean - 博客園及Python中list的實現 - Vito.K - 博客園。
18.__all__的作用
參考Can someone explain __all__ in Python?及python中模塊的__all__屬性
作用是:
If the __all__ above is commented out, this code will then execute to completion, as the default behavior of import * is to import all symbols that do not begin with an underscore, from the given namespace.在引用是,除了__all__列表里指定的屬性,其它都會被隱藏。
19.面向切面編程
參考面向切面編程_百度百科
Aspect Oriented Programming(AOP),面向切面編程。AOP主要實現的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。
八、深度學習相關
設定TensorFlow使用GPU顯存可參考Michael:[Python]設定TensorFlow使用GPU顯存。
附件
一些可能有用的網址:
很全的 Python 面試題 - Python - 伯樂在線
常見的25個python面試問答,讓你順利拿到offer!
Python面試必須要看的15個問題 - Vito.K - 博客園
Python初學者需要注意的問題 - walkingp - 博客園
很全的 Python 面試題 - Python - 伯樂在線
【已完結】
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python list转换成array_一文掌握Python【不定期更新】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智源重大研究方向“智能体系架构与芯片”发
- 下一篇: python百分号用法_python百分