目錄
- 一、Python基礎(chǔ)
- 1. 數(shù)據(jù)類型和變量
- 2. 字符串和編碼
- 3. list 和 tuple
- list
- tuple
- 4. 條件判斷
- 5. 循環(huán)
- 6. dict 和 set
- dict
- set
- 二、函數(shù)
- 1. 調(diào)用函數(shù)
- 2. 定義函數(shù)
- 3. 函數(shù)的參數(shù)
- 位置參數(shù)
- 默認(rèn)參數(shù)
- 可變參數(shù)
- 關(guān)鍵字參數(shù)
- 命名關(guān)鍵字參數(shù)
- 參數(shù)組合
- 4. 遞歸函數(shù)
- 三、高級(jí)特性
- 1. 切片
- 2. 迭代
- 3. 列表生成式
- 4. 生成器
- 5. 迭代器
- 四、函數(shù)式編程
- 1. 高階函數(shù)
- map/reduce
- filter
- sorted
- 2. 返回函數(shù)
- 3. 匿名函數(shù)
- 4. 裝飾器
- 5. 偏函數(shù)
- 五、模塊
- 六、面向?qū)ο缶幊?
- 七、面向?qū)ο蟾呒?jí)編程
- 八、錯(cuò)誤、調(diào)試和測(cè)試
- 1. 錯(cuò)誤處理
- 2. 調(diào)試
- 3. 單元測(cè)試
- 4. 文檔測(cè)試
- 九、IO 編程
- 1. 文件讀寫
- 2. StringIO 和 BytesIO
- 3. 操作文件和目錄
- 4. 序列化
- 十、進(jìn)程和線程
- 1. 多進(jìn)程
- 2. 多線程
- 3. ThreadLocal
- 4. 進(jìn)程 vs. 線程
- 5. 分布式進(jìn)程
- 十一、正則表達(dá)式
- 十二、常用內(nèi)建模塊
- 1. datetime
- 2. collections
一、Python基礎(chǔ)
1. 數(shù)據(jù)類型和變量
-
整數(shù)
-
//表示地板除,整數(shù)地板除整數(shù)結(jié)果還是整數(shù),保留整數(shù)部分 - 沒有大小限制
-
-
浮點(diǎn)數(shù)
-
沒有大小限制,超出了一定范圍就直接使用
inf(無限大)表示
-
沒有大小限制,超出了一定范圍就直接使用
-
字符串
-
使用反斜杠
\表示轉(zhuǎn)義,如\\,\t,\n,\' -
使用
r''表示''內(nèi)部的字符串不轉(zhuǎn)義 -
使用
'''...'''的格式表示多行
-
使用反斜杠
-
布爾值(
True,False)-
and與運(yùn)算,or或運(yùn)算,not非運(yùn)算
-
-
空值(
None) -
變量
- 大小寫字母、數(shù)字和_的組合,不能以數(shù)字開頭
-
常亮
- 通常使用全部大寫的字母表示
2. 字符串和編碼
-
ASCII編碼,由美國(guó)人發(fā)明,無法表示中文等字符 -
GB2312編碼,中國(guó)制定的,用來把中文編碼進(jìn)去。每個(gè)國(guó)家都制定了自己的編碼,就出現(xiàn)了亂碼的情況 -
Unicode編碼,所有語言都編碼在里面。ASCII 編碼是 1 個(gè)字節(jié),而 Unicode 編碼通常是 2 個(gè)字節(jié),造成了浪費(fèi) -
UTF-8編碼,UTF-8 編碼把一個(gè) Unicode 字符根據(jù)不同的數(shù)字大小編碼成 1-6 個(gè)字節(jié),常用的英文字母被編碼成 1 個(gè)字節(jié),漢字通常是 3 個(gè)字節(jié),只有很生僻的字符才會(huì)被編碼成 4-6 個(gè)字節(jié) -
對(duì)于單個(gè)字符的編碼,
ord(char)函數(shù)獲取字符的整數(shù)表示,chr(int)函數(shù)把編碼轉(zhuǎn)換為對(duì)應(yīng)的字符
>>
>
ord
(
'A'
)
65
>>
>
ord
(
'中'
)
20013
>>
>
chr
(
66
)
'B'
>>
>
chr
(
25991
)
'文'
-
Python 對(duì)
bytes類型的數(shù)據(jù)用帶b前綴的單引號(hào)或雙引號(hào)表示:x = b'ABC' -
以 Unicode 表示的 str 通過
encode(code)方法可以編碼為指定(code)的bytes。 -
反過來,使用
decode(code),如果bytes中只有一小部分無效的字節(jié),可以傳入errors='ignore’忽略錯(cuò)誤的字節(jié)
>>
>
b
'\xe4\xb8\xad\xff'
.
decode
(
'utf-8'
,
errors
=
'ignore'
)
'中'
-
len(str)獲取字符串長(zhǎng)度 -
格式化使用占位符(%d,%f,%s,%x(十六進(jìn)制整數(shù)))。如果要輸出
%,轉(zhuǎn)義%% - 另一種格式化字符串的方法是使用字符串的format()方法,它會(huì)用傳入的參數(shù)依次替換字符串內(nèi)的占位符{0}、{1}
>>
>
'Hello, {0}, 成績(jī)提升了 {1:.1f}%'
.
format
(
'小明'
,
17.125
)
'Hello, 小明, 成績(jī)提升了 17.1%'
3. list 和 tuple
list
- list是一種有序的集合,可以隨時(shí)添加和刪除其中的元素
>>
>
classmates
=
[
'Michael'
,
'Bob'
,
'Tracy'
]
>>
>
classmates
[
'Michael'
,
'Bob'
,
'Tracy'
]
-
len(classmates)函數(shù)獲取list元素的個(gè)數(shù) -
使用從0開始的索引訪問每個(gè)元素,超出范圍,會(huì)報(bào)
IndexError的錯(cuò)誤 - 獲取最后一個(gè)元素可以直接使用-1做索引,以此類推,倒數(shù)第二個(gè)-2,倒數(shù)第三個(gè)-3
-
使用
append(str)追加元素,classmates.append('Adam') -
使用
insert(index, str)插入到指定index位置 -
使用
pop()刪除末尾元素,使用pop(index)刪除索引為index的元素
tuple
-
元組。一旦初始化,就不能修改了,和list相似。
classmates = ('Michael', 'Bob', 'Tracy') -
沒有
append(),insert()方法,獲取元素的方法同 list,但是不能再進(jìn)行賦值修改 - tuple 不可變,所以代碼更安全。如果可能,能用 tuple 代替 list 就盡量用 tuple
-
如果要定義只有一個(gè)元素的 tulpe,加上逗號(hào)
,和小括號(hào)區(qū)分開來,a = (1,) - 可變?cè)M
>>
>
t
=
(
'a'
,
'b'
,
[
'A'
,
'B'
]
)
>>
>
t
[
2
]
[
0
]
=
'X'
>>
>
t
[
2
]
[
1
]
=
'Y'
>>
>
t
(
'a'
,
'b'
,
[
'X'
,
'Y'
]
)
4. 條件判斷
if
<
條件判斷
1
>
:
<
執(zhí)行
1
>
elif
<
條件判斷
2
>
:
<
執(zhí)行
2
>
elif
<
條件判斷
3
>
:
<
執(zhí)行
3
>
else
:
<
執(zhí)行
4
>
-
int(str)函數(shù)可以將字符串轉(zhuǎn)成數(shù)字
5. 循環(huán)
- for…in循環(huán)
names
=
[
'Michael'
,
'Bob'
,
'Tracy'
]
for
name
in
names
:
print
(
name
)
-
range(int)函數(shù)生成從 0 到 int-1 的整數(shù)序列 -
list()函數(shù)轉(zhuǎn)換為list
>>
>
list
(
range
(
5
)
)
[
0
,
1
,
2
,
3
,
4
]
- while循環(huán)
sum
=
0
n
=
99
while
n
>
0
:
sum
=
sum
+
n
n
=
n
-
2
print
(
sum
)
-
break,continue
6. dict 和 set
dict
- 使用鍵-值存儲(chǔ)的字典(dictionary)
>>
>
d
=
{
'Michael'
:
95
,
'Bob'
:
75
,
'Tracy'
:
85
}
>>
>
d
[
'Michael'
]
95
-
使用
in判斷key是否存在,'Thomas' in d -
通過dict提供的
get(str, default)方法,如果key不存在,可以返回None,或者自己指定的value,d.get('Thomas', -1) -
使用
pop(key)刪除指定指定鍵值對(duì) - key必須是不可變對(duì)象
set
- set和dict類似,也是一組key的集合,但不存儲(chǔ)value。由于key不能重復(fù),所以,在set中,沒有重復(fù)的key。
>>
>
s
=
set
(
[
1
,
2
,
2
,
3
]
)
>>
>
s
{
1
,
2
,
3
}
-
使用
add(key)函數(shù)添加元素到set -
remove(key)刪除元素 - set可以看成數(shù)學(xué)意義上的無序和無重復(fù)元素的集合,因此,兩個(gè)set可以做數(shù)學(xué)意義上的交集、并集等操作
>>
>
s1
=
set
(
[
1
,
2
,
3
]
)
>>
>
s2
=
set
(
[
2
,
3
,
4
]
)
>>
>
s1
&
s2
{
2
,
3
}
>>
>
s1
|
s2
{
1
,
2
,
3
,
4
}
二、函數(shù)
1. 調(diào)用函數(shù)
- 內(nèi)置函數(shù) https://docs.python.org/zh-cn/3/library/functions.html
- 函數(shù)名其實(shí)就是指向一個(gè)函數(shù)對(duì)象的引用,完全可以把函數(shù)名賦給一個(gè)變量,相當(dāng)于給這個(gè)函數(shù)起了一個(gè)“別名”:
>>
>
a
=
abs
# 變量a指向abs函數(shù)
>>
>
a
(
-
1
)
# 所以也可以通過a調(diào)用abs函數(shù)
1
2. 定義函數(shù)
- 定義一個(gè)函數(shù)要使用def語句,依次寫出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):,然后,在縮進(jìn)塊中編寫函數(shù)體,函數(shù)的返回值用return語句返回。
def
my_abs
(
x
)
:
if
x
<
0
:
return
-
x
else
:
return
x
-
定義一個(gè)空函數(shù)可以使用
pass語句(暫時(shí)還不知道怎么寫函數(shù),占位符,使代碼能夠正常運(yùn)行),pass 也可以用在其他地方,比如 if -
isinstance(param, (type1, type2))函數(shù)檢查param的數(shù)據(jù)類型是否為type1或者type2 - 返回多個(gè)值
import
math
def
move
(
x
,
y
,
step
,
angle
=
0
)
:
nx
=
x
+
step
*
math
.
cos
(
angle
)
ny
=
y
-
step
*
math
.
sin
(
angle
)
return
nx
,
ny
x
,
y
=
move
(
100
,
100
,
60
,
math
.
pi
/
6
)
print
(
x
,
y
)
#151.96152422706632 70.0
#或者
r
=
move
(
100
,
100
,
60
,
math
.
pi
/
6
)
print
(
r
)
#(151.96152422706632, 70.0)
#其實(shí)就是一個(gè)tuple
- 如果函數(shù)沒有 return,會(huì)自動(dòng)返回 None
3. 函數(shù)的參數(shù)
位置參數(shù)
-
類似于
def f(x, y):這種
默認(rèn)參數(shù)
-
類似于
def f(x, y = 1):這種 - 必選參數(shù)在前,默認(rèn)參數(shù)在后
-
調(diào)用時(shí)默認(rèn)參數(shù)可以不按照順序,把參數(shù)名加上即可。比如定義時(shí)
def enroll(name, gender, age=6, city='Beijing'):,而調(diào)用時(shí)enroll('Adam', 'M', city='Tianjin') - 默認(rèn)參數(shù)必須指向不變對(duì)象
可變參數(shù)
- 傳入的參數(shù)個(gè)數(shù)是可變的,可以是1個(gè)、2個(gè)到任意個(gè),還可以是0個(gè)。使用一個(gè)*定義可變參數(shù)
def
calc
(
*
numbers
)
:
sum
=
0
for
n
in
numbers
:
sum
=
sum
+
n
*
n
return
sum
>>
>
calc
(
1
,
2
)
5
>>
>
calc
(
)
0
- 如果調(diào)用時(shí)傳的參數(shù)是 list 或者 tuple,則可以使用以下形式
>>
>
nums
=
[
1
,
2
,
3
]
>>
>
calc
(
*
nums
)
14
*nums 表示把 nums 這個(gè) list 的所有元素作為可變參數(shù)傳進(jìn)去
關(guān)鍵字參數(shù)
- 可變參數(shù)允許你傳入0個(gè)或任意個(gè)參數(shù),這些可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè) tuple。而關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè) dict。使用兩個(gè)*定義關(guān)鍵字參數(shù)
def
person
(
name
,
age
,
**
kw
)
:
print
(
'name:'
,
name
,
'age:'
,
age
,
'other:'
,
kw
)
>>
>
person
(
'Michael'
,
30
)
name
:
Michael age
:
30
other
:
{
}
>>
>
person
(
'Bob'
,
35
,
city
=
'Beijing'
)
name
:
Bob age
:
35
other
:
{
'city'
:
'Beijing'
}
>>
>
person
(
'Adam'
,
45
,
gender
=
'M'
,
job
=
'Engineer'
)
name
:
Adam age
:
45
other
:
{
'gender'
:
'M'
,
'job'
:
'Engineer'
}
- 如果有個(gè) dict,則可以直接使用兩個(gè)**進(jìn)行調(diào)用
>>
>
extra
=
{
'city'
:
'Beijing'
,
'job'
:
'Engineer'
}
>>
>
person
(
'Jack'
,
24
,
**
extra
)
name
:
Jack age
:
24
other
:
{
'city'
:
'Beijing'
,
'job'
:
'Engineer'
}
命名關(guān)鍵字參數(shù)
- 用來限制關(guān)鍵字參數(shù)的名字,只接受部分作為關(guān)鍵字參數(shù)
def
person
(
name
,
age
,
*
,
city
,
job
)
:
print
(
name
,
age
,
city
,
job
)
- *后面的參數(shù)被視為命名關(guān)鍵字參數(shù)
- 如果函數(shù)定義中已經(jīng)有了一個(gè)可變參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符*了
def
person
(
name
,
age
,
*
args
,
city
,
job
)
:
print
(
name
,
age
,
args
,
city
,
job
)
- 命名關(guān)鍵字參數(shù)可以有缺省值,從而簡(jiǎn)化調(diào)用
def
person
(
name
,
age
,
*
,
city
=
'Beijing'
,
job
)
:
print
(
name
,
age
,
city
,
job
)
參數(shù)組合
- 參數(shù)順序:必選參數(shù)(位置參數(shù))、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)
- 對(duì)于任意函數(shù),都可以通過類似func(*tuple, **dict)的形式調(diào)用它,無論它的參數(shù)是如何定義的
4. 遞歸函數(shù)
- 如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)
- 函數(shù)調(diào)用是通過棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,每當(dāng)進(jìn)入一個(gè)函數(shù)調(diào)用,棧就會(huì)加一層棧幀,每當(dāng)函數(shù)返回,棧就會(huì)減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會(huì)導(dǎo)致棧溢出
- 尾遞歸是指,在函數(shù)返回的時(shí)候,調(diào)用自身本身,并且,return語句不能包含表達(dá)式
三、高級(jí)特性
1. 切片
- 取一個(gè) list 或 tuple 的部分元素
-
L[0:3]表示,從索引 0 開始取,直到索引 3 為止,但不包括索引 3。即索引 0,1,2,正好是 3 個(gè)元素 - 如果第一個(gè)索引是 0,則可以省略
- 倒數(shù)第一個(gè)的索引為 -1,使用負(fù)數(shù)時(shí)表示倒數(shù)切片,同理 -1 可以省略
-
L[0:10:step]表示取出前十個(gè)元素中每隔 step 的元素 -
L[:]表示復(fù)制一個(gè) L -
字符串
'xxx'也可以看成是一種 list,每個(gè)元素就是一個(gè)字符
2. 迭代
- 默認(rèn)情況下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時(shí)迭代key和value,可以用for k, v in d.items()
-
字符串也可以進(jìn)行迭代。
for ch in 'ABC': - 通過 collections 模塊的 Iterable 類型可以判斷是否為可迭代對(duì)象
>>
>
from
collections
import
Iterable
>>
>
isinstance
(
'abc'
,
Iterable
)
# str是否可迭代
True
>>
>
isinstance
(
[
1
,
2
,
3
]
,
Iterable
)
# list是否可迭代
True
>>
>
isinstance
(
123
,
Iterable
)
# 整數(shù)是否可迭代
False
-
enumerate(list)函數(shù)可以把一個(gè)list變成索引-元素對(duì),這樣就可以在 for 循環(huán)中同時(shí)迭代索引和元素本身
>>
>
for
i
,
value
in
enumerate
(
[
'A'
,
'B'
,
'C'
]
)
:
.
.
.
print
(
i
,
value
)
.
.
.
0
A
1
B
2
C
3. 列表生成式
- 用來創(chuàng)建 list 的生成式
-
要生成
list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11)) -
[x * x for x in range(1, 11)]用來生成[1x1, 2x2, 3x3, ..., 10x10],即[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] -
[要生成的元素 for 迭代元素 in 迭代對(duì)象 if 元素滿足條件] - 還可以使用兩層循環(huán),可以生成全排列:
>>
>
[
m
+
n
for
m
in
'ABC'
for
n
in
'XYZ'
]
[
'AX'
,
'AY'
,
'AZ'
,
'BX'
,
'BY'
,
'BZ'
,
'CX'
,
'CY'
,
'CZ'
]
4. 生成器
-
一邊循環(huán)一邊計(jì)算的機(jī)制,稱為生成器:
generator - 只要把一個(gè)列表生成式的 [] 改成 (),就創(chuàng)建了一個(gè) generator:
>>
>
L
=
[
x
*
x
for
x
in
range
(
10
)
]
>>
>
L
[
0
,
1
,
4
,
9
,
16
,
25
,
36
,
49
,
64
,
81
]
>>
>
g
=
(
x
*
x
for
x
in
range
(
10
)
)
>>
>
g
<
generator
object
<
genexpr
>
at
0x1022ef630
>
-
通過
next(generator)函數(shù) generator 的下一個(gè)返回值,或者也可以直接使用 for 循環(huán)進(jìn)行迭代 - 如果一個(gè)函數(shù)定義中包含 yield 關(guān)鍵字,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè) generator
- 函數(shù)是順序執(zhí)行,遇到 return 語句或者最后一行函數(shù)語句就返回。而變成 generator 的函數(shù),在每次調(diào)用 next() 的時(shí)候執(zhí)行,遇到 yield 語句返回,再次執(zhí)行時(shí)從上次返回的 yield 語句處繼續(xù)執(zhí)行
- 用 for 循環(huán)調(diào)用 generator 時(shí),拿不到 generator 的 return 語句的返回值。如果想要拿到返回值,必須捕獲 StopIteration 錯(cuò)誤,返回值包含在 StopIteration 的 value 中
5. 迭代器
- 可以被 next() 函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器:Iterator。它們表示一個(gè)惰性計(jì)算的序列
- 生成器都是Iterator對(duì)象,但 list、dict、str 雖然是 Iterable,卻不是 Iterator
- 把 list、dict、str 等 Iterable 變成 Iterator 可以使用 iter() 函數(shù)
- 凡是可作用于 for 循環(huán)的對(duì)象都是 Iterable 類型
四、函數(shù)式編程
1. 高階函數(shù)
- 把函數(shù)作為參數(shù)傳入,這樣的函數(shù)稱為高階函數(shù),函數(shù)式編程就是指這種高度抽象的編程范式
map/reduce
-
map(function,Iterable),對(duì)序列的每個(gè)元素執(zhí)行 function 函數(shù) - reduce 把一個(gè)函數(shù)作用在一個(gè)序列[x1, x2, x3, …]上,這個(gè)函數(shù)必須接收兩個(gè)參數(shù),reduce 把結(jié)果繼續(xù)和序列的下一個(gè)元素做累積計(jì)算,比如:
reduce
(
f
,
[
x1
,
x2
,
x3
,
x4
]
)
=
f
(
f
(
f
(
x1
,
x2
)
,
x3
)
,
x4
)
filter
-
filter(function,Iterable),對(duì)序列的每個(gè)元素執(zhí)行 function 函數(shù),只返回為 True 的元素
sorted
-
sorted(list),從小到大排序 -
sorted(list, k=abs),按照元素的絕對(duì)值從小到大排序,abs 是個(gè)函數(shù) - 默認(rèn)情況下,對(duì)字符串排序,是按照ASCII的大小比較的
-
對(duì)字符串忽略大小寫進(jìn)行排序。
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) -
反向排序。加上第三個(gè)參數(shù)reverse,
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
2. 返回函數(shù)
- A函數(shù)里面定義B函數(shù),A函數(shù)最后 return B函數(shù),調(diào)用A函數(shù)時(shí)返回函數(shù),需要再次調(diào)用這個(gè)函數(shù)
- 返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量。(因?yàn)椴皇橇⒓磮?zhí)行的)
3. 匿名函數(shù)
-
lambda x: x * x就是一個(gè)匿名函數(shù),冒號(hào)前面的 x 表示函數(shù)參數(shù)
4. 裝飾器
-
函數(shù)對(duì)象有一個(gè)
__name__屬性,可以拿到函數(shù)的名字 - 在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式,稱之為“裝飾器”(Decorator)
- @語法
5. 偏函數(shù)
- 用來修改固定函數(shù)參數(shù)的默認(rèn)值,返回一個(gè)新的函數(shù)
-
functools.partial
五、模塊
- 一個(gè).py文件就成為一個(gè)模塊(Module)
-
按目錄來組織模塊的方法稱為包(Package),之后每個(gè)模塊名之前都加上這個(gè)包名。
package.module -
每個(gè)包的目錄下面都必須包含一個(gè)
__init__.py文件,可以為空,也可以有代碼,本身就是一個(gè)模塊,模塊名就是這個(gè)報(bào)名 -
通過在交互環(huán)境下執(zhí)行
import abc,可以檢測(cè)系統(tǒng)是否已經(jīng)存在 abc 模塊 - 任何模塊代碼的第一個(gè)字符串都被視為模塊的文檔注釋
-
__author__變量表示作者,__doc__也可以用來表示文檔注釋 -
sys模塊的argv變量用來保存命令行的所有參數(shù) -
命令行運(yùn)行模塊式,
__name__變量被置為__main__ -
類似
_xxx和__xxx這樣的函數(shù)或變量就是非公開的(private), 不應(yīng)該 被直接引用。是 不應(yīng)該 ,不是 不能 -
安裝第三方模塊,是通過包管理工具
pip完成的 - Anaconda
- 搜索路徑存在 sys 模塊的 path 變量中
-
需要添加自己的搜索路徑時(shí),可以直接使用
sys.path.append('')進(jìn)行添加(運(yùn)行時(shí)修改,運(yùn)行結(jié)束失效)。也可以設(shè)置環(huán)境變量PYTHONPATH
六、面向?qū)ο缶幊?
- 類型通常是大寫開頭的單詞
class
Student
(
object
)
:
pass
object表示繼承的類
-
__init__函數(shù)在對(duì)象初始化的時(shí)候執(zhí)行,第一個(gè)參數(shù)self表示本身 -
類中定義的函數(shù)第一個(gè)參數(shù)永遠(yuǎn)是實(shí)例變量
self -
__開頭的變量為私有變量,只有內(nèi)部才能訪問(其實(shí)Python解釋器把這個(gè)變量改成了
_類名__變量名,所以其實(shí)可以通過_類名__變量名來訪問這個(gè)變量,不同版本的解釋器,名字可能不一樣) -
file-like objec鴨子類型,當(dāng)某個(gè)方法需要某種類型的對(duì)象作為參數(shù)時(shí),并不一定非要這種類型的對(duì)象才可以,只要這個(gè)對(duì)象有相應(yīng)的方法就可以了(動(dòng)態(tài)語言) -
type()返回對(duì)應(yīng)的類型 -
types 模塊,
types.FunctionTypetypes.BuiltinFunctionTypetypes.LambdaTypetypes.GeneratorType -
如果要獲得一個(gè)對(duì)象的所有屬性和方法,可以使用
dir()函數(shù),它返回一個(gè)包含字符串的 list。__xxx__屬性或者方法在調(diào)用時(shí)除了使用'ABC.__xxx__()'還可以直接使用xxx('ABC'),自己寫的類,也可以定義成__xxx__形式 -
hasattr(obj, 'x') # 有屬性'x'嗎setattr(obj, 'y', 19) # 設(shè)置一個(gè)屬性'y'getattr(obj, 'y', default) # 獲取屬性'y' - 實(shí)例屬性優(yōu)先級(jí)高于類屬性
-
使用
del s.name刪除實(shí)例 s 的 name 屬性
七、面向?qū)ο蟾呒?jí)編程
- 可以給實(shí)例綁定屬性或者方法
-
__slots__變量限制實(shí)例添加的屬性,對(duì)于繼承的子類不起作用
__slots__
=
(
'name'
,
'age'
)
# 用tuple定義允許綁定的屬性名稱
-
@property裝飾器獲取屬性值,@attr.setter設(shè)置屬性值 -
多重繼承,集成多個(gè)父類,從而擁有多個(gè)父類的所有方法。這種設(shè)計(jì)稱為
MixIn -
__str__()方法,__repr__()方法 -
__iter__()方法返回一個(gè)迭代對(duì)象,使類可以使用for...in..循環(huán) -
__getitem__()方法使像 list 那樣,可以按照下標(biāo)取出元素 -
__setitem__()方法,把對(duì)象視作 list 或 dict 來對(duì)集合賦值 -
__delitem__方法,用于刪除某個(gè)元素 -
__getattr__()方法,動(dòng)態(tài)返回一個(gè)屬性 -
__call__()方法,對(duì)實(shí)例本身進(jìn)行調(diào)用 -
Callable()判斷一個(gè)對(duì)象能否被調(diào)用 -
枚舉類
Enum,@unique裝飾器檢查保證沒有重復(fù)值 -
type()函數(shù)可以查看一個(gè)類型或變量的類型 -
type()函數(shù)既可以返回一個(gè)對(duì)象的類型,又可以創(chuàng)建出新的類型 -
metaclass元類允許你創(chuàng)建類或者修改類
八、錯(cuò)誤、調(diào)試和測(cè)試
1. 錯(cuò)誤處理
-
try...except...finally...,可以在except語句塊后面加一個(gè)else表示當(dāng)沒有錯(cuò)誤發(fā)生時(shí)執(zhí)行 - 常見的錯(cuò)誤和繼承關(guān)系
-
logging模塊的logging.exception(e)用來記錄錯(cuò)誤信息,但程序打印完錯(cuò)誤信息后會(huì)繼續(xù)執(zhí)行,并正常退出 -
raise語句可以拋出一個(gè)錯(cuò)誤實(shí)例
2. 調(diào)試
-
使用
print()打印 -
assert 表達(dá)式, '錯(cuò)誤信息',表達(dá)式為False時(shí),拋出AssertionError錯(cuò)誤。啟動(dòng)時(shí)加上參數(shù)-O關(guān)閉 assert。python -O err.py -
logging -
Python 的調(diào)試器
pdb -
pdb.set_trace()
3. 單元測(cè)試
4. 文檔測(cè)試
- python 內(nèi)置的 doctest 模塊可以自動(dòng)提取 ‘’‘xxx’’'注釋中的代碼并執(zhí)行測(cè)試
九、IO 編程
1. 文件讀寫
-
open(文件, 模式, encoing, errors)打開一個(gè)文件 -
read()讀取文件所有內(nèi)容 -
close()關(guān)閉文件 -
with語句用法
with
open
(
'/path/to/file'
,
'r'
)
as
f
:
print
(
f
.
read
(
)
)
-
read(size)每次讀取 size 字節(jié)內(nèi)容 -
readline()每次讀取一行內(nèi)容 -
readlines()一次性讀取所有內(nèi)容并按行返回 list -
write()寫文件 -
r讀文件,rb讀二進(jìn)制文件,w寫文件,wb寫二進(jìn)制文件,a追加
2. StringIO 和 BytesIO
-
先創(chuàng)建
StringIO對(duì)象,然后write寫內(nèi)容,getvalue()獲取寫入后的 str - 也可以
>>
>
from
io
import
StringIO
>>
>
f
=
StringIO
(
'Hello!\nHi!\nGoodbye!'
)
>>
>
while
True
:
.
.
.
s
=
f
.
readline
(
)
.
.
.
if
s
==
''
:
.
.
.
break
.
.
.
print
(
s
.
strip
(
)
)
.
.
.
Hello!
Hi!
Goodbye!
-
BytesIO和StringIO一樣,只不過是前者操作二進(jìn)制數(shù)據(jù),后者操作 str
3. 操作文件和目錄
-
os模塊,os.name返回操作系統(tǒng)類型,os.environ操作系統(tǒng)的環(huán)境變量,os.environ.get('key')獲取環(huán)境變量的值
# 查看當(dāng)前目錄的絕對(duì)路徑:
>>
>
os
.
path
.
abspath
(
'.'
)
'/Users/michael'
# 在某個(gè)目錄下創(chuàng)建一個(gè)新目錄,首先把新目錄的完整路徑表示出來:
# os.path.split(),拆分路徑。os.path.split(),合并路徑
>>
>
os
.
path
.
join
(
'/Users/michael'
,
'testdir'
)
'/Users/michael/testdir'
# 然后創(chuàng)建一個(gè)目錄:
>>
>
os
.
mkdir
(
'/Users/michael/testdir'
)
# 刪掉一個(gè)目錄:
>>
>
os
.
rmdir
(
'/Users/michael/testdir'
)
-
os.path.splitext()可以直接得到文件擴(kuò)展名
>>
>
os
.
path
.
splitext
(
'/path/to/file.txt'
)
(
'/path/to/file'
,
'.txt'
)
# 對(duì)文件重命名:
>>
>
os
.
rename
(
'test.txt'
,
'test.py'
)
# 刪掉文件:
>>
>
os
.
remove
(
'test.py'
)
-
復(fù)制函數(shù)可以使用
shutil模塊的copyfile()函數(shù)
# 列出當(dāng)前目錄下的所有目錄
>>
>
[
x
for
x
in
os
.
listdir
(
'.'
)
if
os
.
path
.
isdir
(
x
)
]
[
'.lein'
,
'.local'
,
'.m2'
,
'.npm'
,
'.ssh'
,
'.Trash'
,
'.vim'
,
'Applications'
,
'Desktop'
,
.
.
.
]
4. 序列化
- 變量從內(nèi)存中變成可存儲(chǔ)或傳輸?shù)倪^程稱之為序列化(pickling)
- 把變量?jī)?nèi)容從序列化的對(duì)象重新讀到內(nèi)存里稱之為反序列化,即unpickling
-
pickle模塊的pickle.dumps(obj)方法把任意對(duì)象序列化成一個(gè) bytes -
pickle.dump(object, file)直接寫入到一個(gè) file-like Object -
pickle.loads()反序列化對(duì)象,pickle.load(file)從 file-like Object 中反序列化 -
json模塊 -
如果需要序列化一個(gè)對(duì)象,在對(duì)象中寫一個(gè)方法 function,使用
json.dumps(obj, default=function)即可?;蛘?json.dumps(s, default=lambda obj: obj.__dict__) -
反序列化時(shí),同樣加上
object_hook函數(shù)即可。json.loads(json_str, object_hook=dict2student) - 如果ensure_ascii為True(默認(rèn)值),則輸出保證將所有輸入的非ASCII字符轉(zhuǎn)義。如果確保ensure_ascii為False,這些字符將原樣輸出
十、進(jìn)程和線程
- 線程是最小的執(zhí)行單元,而進(jìn)城由至少一個(gè)線程組成
1. 多進(jìn)程
-
fork() -
multiprocessing模塊
from
multiprocessing
import
Process
import
os
# 子進(jìn)程要執(zhí)行的代碼
def
run_proc
(
name
)
:
print
(
'Run child process %s (%s)...'
%
(
name
,
os
.
getpid
(
)
)
)
if
__name__
==
'__main__'
:
print
(
'Parent process %s.'
%
os
.
getpid
(
)
)
p
=
Process
(
target
=
run_proc
,
args
=
(
'test'
,
)
)
print
(
'Child process will start.'
)
p
.
start
(
)
p
.
join
(
)
print
(
'Child process end.'
)
執(zhí)行結(jié)果
Parent process
928
.
Process will start
.
Run child process test
(
929
)
.
.
.
Process end
.
-
Pool對(duì)象 -
subprocess模塊創(chuàng)建子進(jìn)程
2. 多線程
-
threading模塊。current_thread()返回當(dāng)前線程的實(shí)例 - 多進(jìn)程變量各自拷貝一份,互不影響;多線程之間共享變量
-
通過
threading.Lock()創(chuàng)建鎖來解決多線程之間的共享變量問題
balance
=
0
lock
=
threading
.
Lock
(
)
def
run_thread
(
n
)
:
for
i
in
range
(
100000
)
:
# 先要獲取鎖:
lock
.
acquire
(
)
try
:
# 放心地改吧:
change_it
(
n
)
finally
:
# 改完了一定要釋放鎖:
lock
.
release
(
)
-
解釋器的
GIL全局鎖導(dǎo)致即使100個(gè)線程跑在100核CPU上,也只能用到1個(gè)核
3. ThreadLocal
- 用一個(gè)全局 dict 存放所有的線程需要傳遞的參數(shù),然后以 thread 自身作為 key 獲得線程對(duì)應(yīng)的參數(shù)
global_dict
=
{
}
def
std_thread
(
name
)
:
std
=
Student
(
name
)
# 把std放到全局變量global_dict中:
global_dict
[
threading
.
current_thread
(
)
]
=
std
do_task_1
(
)
do_task_2
(
)
def
do_task_1
(
)
:
# 不傳入std,而是根據(jù)當(dāng)前線程查找:
std
=
global_dict
[
threading
.
current_thread
(
)
]
.
.
.
def
do_task_2
(
)
:
# 任何函數(shù)都可以查找出當(dāng)前線程的std變量:
std
=
global_dict
[
threading
.
current_thread
(
)
]
.
.
.
-
ThreadLocal對(duì)象
4. 進(jìn)程 vs. 線程
- 多任務(wù),設(shè)計(jì) Master-Worker 模式,Master 負(fù)責(zé)分配任務(wù)(一個(gè)),Worker 負(fù)責(zé)執(zhí)行任務(wù)(多個(gè))
- 多進(jìn)程模式穩(wěn)定性高,開銷大(最早的Apache)
- 多線程任何一個(gè)線程掛掉都可能導(dǎo)致進(jìn)程掛掉,效率比多進(jìn)程高(IIS 服務(wù)器)
- IIS 和 Apache 現(xiàn)在又有多進(jìn)程+多線程的混合模式
- 線程切換(多進(jìn)程或者多線程之間進(jìn)行切換,也是需要耗時(shí)的,多任務(wù)一旦多了,就會(huì)消耗掉所有系統(tǒng)資源,什么事也做不了)
- 計(jì)算密集型和 IO 密集型
- 計(jì)算密集型需要消耗的 CPU 資源較多,計(jì)算密集型任務(wù)同時(shí)進(jìn)行的數(shù)量應(yīng)當(dāng)?shù)扔?CPU 的核心數(shù)
- Python 運(yùn)行效率低,不適合做計(jì)算密集型的任務(wù)
- IO 密集型任務(wù)越多,CPU 效率越高,99%的時(shí)間都花在 IO 上
- 異步 IO(Nginx 是支持異步 IO 的服務(wù)器)。事件驅(qū)動(dòng)模型
5. 分布式進(jìn)程
十一、正則表達(dá)式
-
re模塊,re.match(r'正則表達(dá)式', str)方法進(jìn)行匹配,成功返回一個(gè) Match 對(duì)象,否則返回 None -
re.split(r'正則表達(dá)式', str)切割字符串 -
使用
()進(jìn)行分組,在Match對(duì)象上使用group(0)方法,獲取原始字符串,后面一次1,2…獲取第1,2…個(gè)子串 -
默認(rèn)是貪婪匹配,后面加一個(gè)
?表示非貪婪匹配
>>
>
re
.
match
(
r
'^(\d+?)(0*)$'
,
'102300'
)
.
groups
(
)
(
'1023'
,
'00'
)
- 如果一個(gè)正則表達(dá)式會(huì)多次去匹配,建議先預(yù)編譯,后面就不會(huì)再進(jìn)行正則表達(dá)式的編譯了,而直接進(jìn)行匹配
>>
>
import
re
# 編譯:
>>
>
re_telephone
=
re
.
compile
(
r
'^(\d{3})-(\d{3,8})$'
)
# 使用:
>>
>
re_telephone
.
match
(
'010-12345'
)
.
groups
(
)
(
'010'
,
'12345'
)
>>
>
re_telephone
.
match
(
'010-8086'
)
.
groups
(
)
(
'010'
,
'8086'
)
十二、常用內(nèi)建模塊
1. datetime
- 處理日期和時(shí)間的標(biāo)準(zhǔn)庫
-
datetime.now()獲取當(dāng)前的datetime,2015-05-18 16:28:07.198690 - 獲取指定的時(shí)間
>>
>
from
datetime
import
datetime
>>
>
dt
=
datetime
(
2015
,
4
,
19
,
12
,
20
)
# 用指定日期時(shí)間創(chuàng)建datetime
>>
>
print
(
dt
)
2015
-
04
-
19
12
:
20
:
00
- 轉(zhuǎn)換為時(shí)間戳,timestamp 是一個(gè)浮點(diǎn)數(shù)。如果有小數(shù)位,小數(shù)位表示毫秒數(shù)。
>>
>
from
datetime
import
datetime
>>
>
dt
=
datetime
(
2015
,
4
,
19
,
12
,
20
)
# 用指定日期時(shí)間創(chuàng)建datetime
>>
>
dt
.
timestamp
(
)
# 把datetime轉(zhuǎn)換為timestamp
1429417200.0
- 時(shí)間戳轉(zhuǎn)換為 datetime
>>
>
from
datetime
import
datetime
>>
>
t
=
1429417200.0
>>
>
print
(
datetime
.
fromtimestamp
(
t
)
)
2015
-
04
-
19
12
:
20
:
00
-
datetime.utcfromtimestamp(t)直接轉(zhuǎn)換到 UTC 標(biāo)準(zhǔn)時(shí)區(qū)的時(shí)間 - str 轉(zhuǎn)換成 datetime
>>
>
from
datetime
import
datetime
>>
>
cday
=
datetime
.
strptime
(
'2015-6-1 18:19:59'
,
'%Y-%m-%d %H:%M:%S'
)
>>
>
print
(
cday
)
2015
-
06
-
01
18
:
19
:
59
- datetime 轉(zhuǎn)換為 str
>>
>
from
datetime
import
datetime
>>
>
now
=
datetime
.
now
(
)
>>
>
print
(
now
.
strftime
(
'%a, %b %d %H:%M'
)
)
Mon
,
May
05
16
:
28
-
對(duì) datetime 進(jìn)行
+,-運(yùn)算符操作
>>
>
from
datetime
import
datetime
,
timedelta
>>
>
now
=
datetime
.
now
(
)
>>
>
now
datetime
.
datetime
(
2015
,
5
,
18
,
16
,
57
,
3
,
540997
)
>>
>
now
+
timedelta
(
hours
=
10
)
datetime
.
datetime
(
2015
,
5
,
19
,
2
,
57
,
3
,
540997
)
>>
>
now
-
timedelta
(
days
=
1
)
datetime
.
datetime
(
2015
,
5
,
17
,
16
,
57
,
3
,
540997
)
>>
>
now
+
timedelta
(
days
=
2
,
hours
=
12
)
datetime
.
datetime
(
2015
,
5
,
21
,
4
,
57
,
3
,
540997
)
-
datetime 類型的屬性
tzinfo,用來設(shè)置時(shí)區(qū) - 時(shí)區(qū)轉(zhuǎn)換
2. collections
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

