跟著廖雪峰老師的Python教程學(xué)習(xí)Python3,遇到需要注意的地方寫到這里,方便以后查閱總結(jié),溫故知新。感謝廖雪峰老師!
基礎(chǔ)
Python中不限定數(shù)值大小
除法: / 普通除法,浮點(diǎn)型, // 取整數(shù)部分, % 取余
Python提供了==ord()==函數(shù)獲取字符的整數(shù)表示,==chr()==函數(shù)把編碼轉(zhuǎn)換為對應(yīng)的字符
Python的字符串類型是str, 以字節(jié)為單位的bytes, 用 b'abc' 表示,讀取字節(jié)流需要用bytes
編碼encode():
'ABC'.encode('ascii') = b'ABC','中文'.encode('utf-8')解碼decode():
b'ABC'.decode('ascii') = 'ABC'計(jì)算str包含多少個(gè)字符,可以用len()函數(shù),
len('abc') = 3-
一般加這兩行,說明使用python3,編碼方式是utf-8
#!/usr/bin/env python3 # -*- coding: utf-8 -*- 占位符:%d 整數(shù),%f 浮點(diǎn)數(shù),%s 字符串,%x 十六進(jìn)制整數(shù),%% 轉(zhuǎn)義 %,%.2f 保留2為小數(shù)
list:l = [1, 2, 3, 'a'], 不同類型的元素也可以放到一個(gè)list里, 可操作的函數(shù):append() = add(), insert(index, value), extend(list) = addAll(), count() = size(), clear(), copy(), pop(value), remove(index), reverse(), sort() ...
tuple: t = (1, 2, 4), 不可變list, 當(dāng)有一個(gè)元素是 t = (1,) 用 , 區(qū)分
條件判斷:if, elif, else
循環(huán):
for x in ...:,while boolean:生成序列:
range(5), 轉(zhuǎn)換成list/tuple:list/tuple(range(5))字典:dict = {'a': 1, 'b': 2}, 相當(dāng)于Java的Map, dict的key必須是不可變對象, 可操作函數(shù):setdefault(), get(), clear(), copy() ...
集合:set:s = set([1, 2, 3]) / s = {1, 2, 3}, 相當(dāng)于Java的Set, add(), remove(), & 交集, | 并集
函數(shù)
Python的內(nèi)置函數(shù) (注意函數(shù)名不要與內(nèi)置函數(shù)重名)
定義函數(shù):def,空函數(shù):pass
判斷類型:isinstance(x, A_tuple), 判斷實(shí)例:issubclass(x, A_tuple)
-
函數(shù)可以返回多個(gè)值,但本質(zhì)上是返回一個(gè)tuple!(例子中的 angel=0 表示默認(rèn)值,必選參數(shù)在前,默認(rèn)參數(shù)在后,默認(rèn)參數(shù)必須指向不變對象!)
import math def move(x, y, step, angle=0): nx = x + step * math.cos(angle) ny = y + step * math.sin(angle) return nx, ny r = move(100, 100, 50, 30) print(r) -
可變參數(shù):
def calc(*nums): pass, 在參數(shù)前加個(gè)星號(hào),即表示為可變參數(shù),0-n都可以,如果想傳入list 或者 tuple,可以把在變量錢加個(gè)星號(hào)轉(zhuǎn)換成可變數(shù)組:nums = [1, 2, 3] print(calc(*nums)) 關(guān)鍵字函數(shù):
**kw: 入?yún)⑹莇ict,好處是可以控制參數(shù)的傳入命名關(guān)鍵字參數(shù):
def person(name, age, *, city, job):,用星號(hào)分隔,后面的視為命名關(guān)鍵字函數(shù),可以有默認(rèn)值。調(diào)用時(shí)必須傳入key:city=HangZhou五種參數(shù)類型的定義順序:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù),
def f1(a, b, c=0, *args, **kw): pass-
任意函數(shù)都可以通過:
fun(*args, **kw)調(diào)用,無論參數(shù)如何定義,-
*args是可變參數(shù),args接收的是一個(gè)tuple -
**kw是關(guān)鍵字參數(shù),kw接收的是一個(gè)dict - 命名的關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名,同時(shí)可以提供默認(rèn)值
- 定義命名的關(guān)鍵字參數(shù)在沒有可變參數(shù)的情況下不要忘了寫分隔符*,否則定義的將是位置參數(shù)
-
高級(jí)特性
切片(Slice):L是個(gè)list:
L[0:3],L[:3]0 可省略,L[:10:2]取前10個(gè)數(shù),步長為2,L[:]復(fù)制一個(gè)L. tuple, str等都可以切片迭代:迭代dict的key:
for key in d, 迭代dict的value:for value in d.values(), 同時(shí)迭代dict:for k, v in d.items(), 字符串也可以迭代,通過isinstance('abc', Iterable)判斷是否可以迭代。多個(gè)變量也可迭代:
for x, y in [(1, 1), (2, 4), (3, 9)]: pring(x, y), Python內(nèi)置的enumerate函數(shù)可以把一個(gè)list變成索引-元素對, 這樣就可以在for循環(huán)中同時(shí)迭代索引和元素本身列表生成式:寫列表生成式時(shí),把要生成的元素x * x放到前面,后面跟for循環(huán),
[x * x for x in range(1, 11)], 還可以跟 if 判斷,還可再跟 for 循環(huán),[m + n for m in 'ABC' for n in 'XYZ'], 注意是方括號(hào),如果是小括號(hào)就是生成器了-
生成器(generator):如果一個(gè)函數(shù)定義中包含yield關(guān)鍵字,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè)generator, yield相當(dāng)于print,但是每遇到y(tǒng)ield就會(huì)中斷
楊輝三角形:def triangles(): row = [1] while True: yield row row = [1] + [row[i] + row[i + 1] for i in range(0, len(row) - 1)] + [1] n = 0 for t in triangles(): print(t) n += 1 if n == 10: break -
迭代器:注意區(qū)分Iterable和Iterator
- Iterable: 可直接作用于for循環(huán)的
- Iterator: 可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對象,直到?jīng)]有對象時(shí)拋出StopIteration錯(cuò)誤
generator都是 Iterator 對象,但 list,dict,str雖然是 Iterable,卻不是Iterator
使用iter()函數(shù),可以把Iterable變成Iterator。Iterator是一個(gè)數(shù)據(jù)流,惰性計(jì)算,所以可以表示無限大的數(shù)據(jù)流。
for循環(huán)的本質(zhì)就是不斷調(diào)用next()函數(shù)實(shí)現(xiàn)的
函數(shù)式編程
-
高階函數(shù):變量可以指向函數(shù)
f = abs,函數(shù)名是什么呢? 函數(shù)名其實(shí)就是指向函數(shù)的變量。編寫高階函數(shù),就是讓函數(shù)的參數(shù)能夠接收別的函數(shù)。def wtf(a, b, f): return f(a) + f(b) print(wtf(-1, 2, abs))高階函數(shù)舉例:
- map:map(f, Iterable) 接收兩個(gè)參數(shù),函數(shù)和Iterable, map將函數(shù)作用于每一個(gè)元素,并返回一個(gè)Iterator。Iterator是惰性的,可以通過list()把整個(gè)結(jié)果計(jì)算出來,并返回一個(gè)list
- reduce:reduce把一個(gè)函數(shù)作用在一個(gè)序列[x1, x2, x3, ...]上,取前兩個(gè)元素算出的結(jié)果與下一個(gè)元素繼續(xù)計(jì)算, 就像這樣:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4) - filter:filter()也接收一個(gè)函數(shù)和一個(gè)序列。filter把函數(shù)作用于序列,返回True保該留元素,F(xiàn)alse丟棄該元素。同樣也返回一個(gè)Iterator 惰性序列。
例如序列中的空字符串刪掉:
list(filter(lambda s: s and s.strip(), ['A', '', 'B', None, 'C', ' '])) # 結(jié)果: ['A', 'B', 'C']- sorted:對數(shù)字,按大小asc排序,對字符串,ASCII碼排序, 例如:
sorted([36, 5, -12, 9, -21], key=abs),還可以傳入func和是否反轉(zhuǎn):sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
-
返回函數(shù):高階函數(shù)除了可以接受函數(shù)作為參數(shù)外,還可以把函數(shù)作為結(jié)果值返回。
像這樣:當(dāng)調(diào)用lazy_sum()時(shí),并沒有返回結(jié)果,而是返回了sum函數(shù)(變量),再次調(diào)用會(huì)返回一個(gè)新函數(shù)!每次的調(diào)用結(jié)果互不影響!def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum閉包:返回閉包時(shí)牢記的一點(diǎn)就是:返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量。
因?yàn)榉祷匾粋€(gè)函數(shù)時(shí),該函數(shù)并未執(zhí)行!所以不要引用可能會(huì)變化的變量 匿名函數(shù):lambda表達(dá)式
lambda x: x * x-
裝飾器(Decorator):在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式,稱為裝飾器。本質(zhì)上decorator就是一個(gè)返回函數(shù)的高階函數(shù)。如果需要給decorator傳入?yún)?shù),則需要編寫一個(gè)返回decorator的高階函數(shù)。一個(gè)完整的decorator如下:注意:裝飾器不能改變原函數(shù)的行為
import functools def log(func): @functools.wraps(func) ##@functools.wraps(func) 是為了保證裝飾器不會(huì)對裝飾器函數(shù)造成影響 def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper帶參數(shù)的decorator:
import functools def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator函數(shù)如果沒有顯示的return,則會(huì)return None
偏函數(shù):functools模塊提供的一個(gè)功能,例如:
int2 = functools.partial(int, base=2)這樣調(diào)用int2時(shí),base默認(rèn)就是2了,不用再傳一遍,當(dāng)然也可以傳其他值,更靈活。偏函數(shù)可以接收函數(shù)對象,*args, **kw這三個(gè)參數(shù)。
模塊
Python中一個(gè).py文件就是一個(gè)模塊(module). Python中有包(package)的概念,每個(gè)包下必須要有__init__.py文件,用于區(qū)分普通目錄與Python的包。 __init__.py 也是一個(gè)模塊,它的模塊名是包的名稱。 包可以有多級(jí)。注意創(chuàng)建的模塊名不要與Python自帶的模塊名沖突,否則無法導(dǎo)入自帶模塊,比如 sys 模塊。
-
使用模塊:
import sys之后就可以使用 sys 提供的功能了。例如
sys.argv, sys的argv變量,用list存儲(chǔ)了命令行的所有參數(shù),argv至少有一個(gè)元素,就是文件名稱。
其他注意的地方:- 任何模塊代碼的第一個(gè)字符串都被視為模塊的文檔注釋
- 使用author 把模塊作者寫進(jìn)去,
__author__ = 'DreamYoung' - 命令行運(yùn)行測試:
if __name__ = '__main__' - 作用域:
__xxx__是特殊變量,一般不要用這種變量名,模塊的文檔注釋可以用__doc__訪問,__xx是private函數(shù)或變量,不應(yīng)該被外部模塊直接引用(Python并沒有限制),其他函數(shù)或變量為public。注意封裝與抽象。
-
安裝第三方模塊:通過包管理工具pip完成,由于是Python3,應(yīng)該使用pip3,比如安裝處理圖像的工具庫Pillow:
pip3 install Pillow(Python解釋器搜索模塊路徑放到sys.path變量中,如果找不到可以設(shè)置下環(huán)境變量PYTHONPATH)其他常用模塊:
- MySQL的驅(qū)動(dòng)
mysql-connector-python, - 科學(xué)計(jì)算的NumPy庫
numpy - 生成文本的模板工具
Jinja2
- MySQL的驅(qū)動(dòng)