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

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
