python語言基礎(傻瓜式文檔)

python語言基礎

數據存儲

思考

思考:爲何使用計算機?
爲了存儲數據、處理數據

思考:數據存在哪裏?
數據存儲在內存中

思考:內存是怎麼存儲數據的?
首先要弄清楚怎麼存儲數字
複製代碼

內存

內存:是計算機存儲數的介質
抽象內存:一個開關,有兩種狀態,開啓和關閉,一種對應1,一種對應0。把8個開關放到一間房子裏,能夠稱這間房子爲「一個字節」,一個開關表明的是一位。每一個房間都有門牌號,看作「地址」。把無數個房間羅列起來組成摩天大廈,能夠把摩天大廈當作內存。
複製代碼

單位

1bit
8bit      ==    1字節
1024字節  ==    1k
1024k     ==    1M
1024M     ==    1G
1024G     ==    1T
複製代碼

進制

二進制:逢2進1
        0 1
        1 + 1 = 10
八進制:逢8進1
        0 1 2 3 4 5 6 7
        1 + 7 = 10
十進制:逢10進1
        0 1 2 3 4 5 6 7 8 9
        1 + 9 = 10
十六進制:逢16進1
        0 1 2 3 4 5 6 7 8 9 a b c d e f
        1 + f = 10
複製代碼

進制轉換

十進制轉二進制
    公式:倒除法,餘數逆序
二進制轉十進制
    公式:當前的數字(0、1)乘以2的位數次方,在相加
    1001 -> 1 x 2^3 + 0 x 2^2 + 0 x 2^1 + 1 x 2^0 
八進制轉二進制
    公式:【一轉三位】八進制的一位至關於二進制的三位,計算時按十進制轉換,不足三位高位補0
二進制轉八進制
    公式:【三位一取】從低位開始,每三位獲得一個八進制數字,最後高位不足則補0
十六進制轉二進制
    公式:【一轉四位】十六進制的一位至關於二進制的四位,計算時按十進制轉換,不足四位高位補0
二進制轉十六進制
    公式:【四位一取】從低位開始,每四位獲得一個十六進制數字,最後高位不足則補0
複製代碼

內存中存儲的數據

存儲數據:
    一、計算機先開闢空間,在存儲數據,計算機開闢空間的最小單位是字節
    二、在數據存儲時,用最高位標識符號位,0表示正數,1表示複數
複製代碼

原碼、補碼、反碼

1    -1

原碼:規定了字節數,寫明瞭符號位,獲得了數據的原碼
    思考:內存是以數據原碼的形式存儲的嗎?

     0000 0000  0000 0000  0000 0000  0000 0001
+    1000 0000  0000 0000  0000 0000  0000 0001
---------------------------------------------------
     1000 0000  0000 0000  0000 0000  0000 0010   -2

    結論:不以原碼的形式存儲數據

反碼:正數的反碼就是其原碼,負數的反碼事其原碼的符號位不變其餘位取反
    思考:內存是以數據反碼的形式存儲的嗎?
     0000 0000  0000 0000  0000 0000  0000 0001
+    1111 1111  1111 1111  1111 1111  1111 1110
--------------------------------------------------- 
     1111 1111  1111 1111  1111 1111  1111 1111

    結論:不以反碼的形式存儲數據

補碼:正數的補碼是其原碼(正數三碼合一),負數的補碼是反碼加1
 
     0000 0000  0000 0000  0000 0000  0000 0001
+    1111 1111  1111 1111  1111 1111  1111 1111
---------------------------------------------------  
  1  0000 0000  0000 0000  0000 0000  0000 0000

  加法最後獲得的1溢出了,沒有存儲到內存中
  
    結論:以補碼的形式存儲數據
複製代碼

第一個python程序

# python程序的文件以.py結尾
# python程序的文件名之後最好不要有中文


# 交互模式
# 黑屏終端輸入 python 進入交互模式
# 輸入 exit() 退出交互模式


# 命令模式
# 輸出 將引號內的字符串輸出到黑屏終端上
print("sunck is a good man! phone is 13691511443")
# 執行 進入程序所在目錄,執行 python 文件名
複製代碼

註釋

# 單行註釋,只能註釋一行

# 多行註釋
# 根據對象的引用計數器,對象建立會給對象一個引用計數器屬性,若是該屬性的值爲0,那麼該對象會被釋放。建立了一個字符串對象,可是沒有任何的引用,因此計數器爲0.
''' print("sunck is a good man") print("sunck is a nice man") '''

""" print("sunck is a cool man") print("sunck is a handsome man") """

print("sunck is a very good man")
複製代碼

輸入與輸出

輸入

# 輸入:從外部獲取變量的值
# input:阻塞,等待輸入
name = input()
print("---------------------")
print(name)
複製代碼

輸出

# 輸出:打印到屏幕上一些信息
# 能夠接受多個字符串,用逗號分隔
# 在寫python程序時切記不要使用中文字符
print("sunck is a good man", "sunck is a nice man", 18)
複製代碼

python數據類型

一、Number(數字)
    整數
    浮點數
    複數

二、String(字符串)
    "sunck is a good man"
    'sunck is a nice man'

三、Boolean(布爾值)
    表示真假的值

四、None(空值)

五、list(列表)

六、tuple(元組)

七、dict(字典)

八、set(集合)
複製代碼

標識符

標識符的做用:給變量、函數等命名的

什麼是標識符:是一串字符串(注意:字符串未必是標識符)

標識符的規則:
    一、只能由字母、數字、下劃線組成
    二、開頭不能是數字
    三、不能是python的關鍵字  
        ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
    四、區分大小寫
    五、見名知意

    注意:在python3中,非ASCII標識符也是容許的了(可是慎用)
''' 複製代碼

變量與常量

''' 變量: 概述: 一、程序可操做的存儲區名稱 二、程序運行過程期間能改變的數據 三、每一個變量都有特定的類型 做用: 將不一樣類型的數據存儲到內存 定義變量: 變量名 = 數據值 注意:變量在使用前必須先定義,不然會出現錯誤 刪除變量: del 變量名 注意:刪除後變量沒法引用 '''
# print("num =", num)
age = 18
print("age =", age)
del age
# print("age =", age)

''' 常量:程序運行期間不能改變的數據 '''
複製代碼

運算符與表達式

概念

表達式:由變量、常量和運算符組成的式子稱爲表達式

閱讀表達式:
    一、閱讀表達式的功能
    二、閱讀表達式的值
複製代碼

算數運算符與算數運算表達式

''' 算術運算符: + - * / % ** // 加 減 乘 除 取模 求冪 取整 '''
''' 算術運算表達式 功能:進行符號對應的算術運算,不會修改變量的值 值:相關算術運算的結果 '''
num1 = 10
num2 = 3
print(num1 + num2)
print(num1 - num2)
print(num1 * num2)
print(num1 / num2)
print(num1 % num2)
print(num1 ** num2)
print(num1 // num2)
複製代碼

賦值運算符和賦值運算表達式

''' 賦值運算符 = '''
''' 賦值運算表達式 格式:變量 = 表達式 功能:計算右側表達式的值,並賦值給等號左側的變量 值:賦值結束後變量的值 '''
num3 = 10
num4 = num3 + 2

複製代碼

複合運算符

''' 複合運算符: += -= *= /= %= **= //= a += b --> a = a + b a -= b --> a = a - b a *= b --> a = a * b a /= b --> a = a / b a %= b --> a = a % b a **= b --> a = a ** b a //= b --> a = a // b '''
複製代碼

位運算符

''' 位運算符: & 按位與運算符:參與運算的兩個值,若是兩個相應位都爲1,則該位結果爲1,不然爲0 | 按位或運算符:參與運算的兩個值,若是兩個相應位有一個爲1時,則該位結果爲1,不然爲0 ^ 按位異或運算符:參與運算的兩個值,若是兩個相應不一樣時,則該位結果爲1,不然爲0 ~ 按位取反運算符:對數據的每一個二進制位進行取反操做,把1變爲0,把0變爲1 << 左移運算符:運算數的各二進制所有左移若干位,由<<右側數字指定移動位數,高位丟棄,低位補0 >> 右移運算符:運算數的各二進制所有右移若干位,由>>右側數字指定移動位數 '''
print(5 & 7)
print(5 | 7)
print(5 ^ 7)
print(~5)
print(2 << 2)
print(11 >> 2)
複製代碼

關係運算符與關係運算表達式

''' 關係運算符 == != > < >= <= 等於 不等於 大於 小於 大於等於 小於等於 '''
''' 關係運算表達式 格式:表達式1 關係運算符 表達式2 功能:計算表達式1和表達式2的值 值: 若是關係成立,則整個關係運算表達式的值爲真,若是關係不成立,則整個關係運算表達式的值爲假 '''
if 1==1:
    print("sunck is a handsome man!")

複製代碼

邏輯運算符與邏輯運算表達式

''' 邏輯運算符 邏輯與 邏輯或 邏輯非 '''

''' 邏輯與運算符 and 邏輯與運算表達式 格式:表達式1 and 表達式2 功能:首先計算「表達式1」的值,若表達式1的值爲真則計算「表達式2」的值 值: 一、若是表達式1的值爲真,表達式2的值爲真,則邏輯與運算表達式的值爲真 二、若是表達式1的值爲真,表達式2的值爲假,則邏輯與運算表達式的值爲假 三、若是表達式1的值爲假,表達式2的值爲真,則邏輯與運算表達式的值爲假 四、若是表達式1的值爲假,表達式2的值爲假,則邏輯與運算表達式的值爲假 總結:有一個爲假就爲假 '''
a = 2
b = 1
if a - 1 and b + 1:
    print("sunck is a good man!")
else:
    print("sunck is a nice man!")

複製代碼

''' 邏輯或 or 邏輯或運算表達式 格式:表達式1 or 表達式2 功能:首先計算「表達式1」的值,若是表達式1的值爲假,則繼續計算「表達式2」的值 值: 一、若是表達式1的值爲真,表達式2的值爲真,則邏輯或運算表達式的值爲真 二、若是表達式1的值爲真,表達式2的值爲假,則邏輯或運算表達式的值爲真 三、若是表達式1的值爲假,表達式2的值爲真,則邏輯或運算表達式的值爲真 四、若是表達式1的值爲假,表達式2的值爲假,則邏輯或運算表達式的值爲假 總結:有一個爲真就爲真 '''
c = 2
d = 1
if c - 1 or print("123"):
    print("sunck is a very good man!")
else:
    print("sunck is a very nice man!")

複製代碼

邏輯與、邏輯或的特性

短路原則:
    表達式1 and 表達式2 and 表達式3 and …… and 表達式n
        從左至右依次計算表達式的值,直到遇到某個表達式的值爲假就中止計算
    表達式1 or 表達式2 or 表達式3 or …… or 表達式n
        從左至右依次計算表達式的值,直到遇到某個表達式的值爲真就中止計算
複製代碼

''' 邏輯非 not 邏輯非運算表達式 格式:not 表達式 值: 一、若是「表達式」的值爲真,則邏輯非運算表達式的值爲假 二、若是「表達式」的值爲假,則邏輯非運算表達式的值爲真 總結:顛倒黑白 '''
e = 1
if not e:
    print("sunck is a very very good man!")
else:
    print("sunck is a very very nice man!")
複製代碼

成員運算符

''' 成員運算符 格式: x in seq x not in seq in:若是在指定的序列中找到值則返回真,不然返回假 not in:若是在指定的序列中沒有找打值則返回真,不然返回假 '''
複製代碼

身份運算符

''' 身份運算符 格式: obj1 is obj2 obj1 is not obj2 is:判斷兩個標識符是否引用同一個對象,相同返回真,不然返回假 is not:判斷兩個標識符是否引用不一樣對象,不一樣返回真,不然返回假 '''

複製代碼

運算符優先級

''' 運算符的優先級: ** 指數 ~ + - 按位取反和一元加減號 * / % // + - 加法減法 << >> & | ^ < > <= >= == != <> = *= /= %= //% += -= **= is is not in not in and or not '''

複製代碼

條件控制語句

''' if語句 '''

''' if-else 語句 '''

''' if-elif-else語句 格式: if 表達式1: 語句1 elif 表達式2: 語句2 …… elif 表達式n: 語句n else: 語句e 邏輯:當程序執行到if-elif-else語句時,首先計算「表達式1」的值,若是「表達式1」的值爲真,則執行「語句1」,執行完「語句1」則結束整個if-elif-else語句繼續向下執行。若是「表達式1」的值爲假,則計算「表達式2」的值,若是「表達式2」的值爲真,則執行「語句2」,執行完「語句2」則結束整個if-elif-else語句繼續向下執行。若是「表達式2」的值爲假,則計算「表達式3」的值。如此進行下去,直到某個表達式的值爲真爲止。若是全部的表達式都爲假,且有else語句則執行「語句e」 深入理解(精髓):每個(else if)else都是對它上面全部表達式的否認 '''
''' 從該控制檯輸入一個年齡 小於0 輸入有誤 0~1 嬰兒 2~6 幼兒 7~14 兒童 15~18 少年 19~30 青年 31~40 壯年 41~50 中年 51~150 老年 151~ 妖精 '''

age = int(input("輸入一個年齡:"))
# if age <= 0:
# print("輸入錯誤")
# if age > 0 and age <= 1:
# print("嬰兒")
# if age >= 2 and age <= 6:
# print("幼兒")
# if age >= 7 and age <= 14:
# print("兒童")
# if age >= 15 and age <= 18:
# print("少年")
# if age >= 19 and age <= 30:
# print("青年")
# if age >= 31 and age <= 40:
# print("壯年")
# if age >= 41 and age <= 50:
# print("中年")
# if age >= 51 and age <= 150:
# print("老年")
# if age > 150:
# print("妖怪")


# if age <= 0:
# print("輸入錯誤")
# elif age > 0 and age <= 1:
# print("嬰兒")
# elif age >= 2 and age <= 6:
# print("幼兒")
# elif age >= 7 and age <= 14:
# print("兒童")
# elif age >= 15 and age <= 18:
# print("少年")
# elif age >= 19 and age <= 30:
# print("青年")
# elif age >= 31 and age <= 40:
# print("壯年")
# elif age >= 41 and age <= 50:
# print("中年")
# elif age >= 51 and age <= 150:
# print("老年")
# else:
# print("妖怪")




if age <= 0:
    print("輸入錯誤")
elif  age <= 1:
    print("嬰兒")
elif  age <= 6:
    print("幼兒")
elif  age <= 14:
    print("兒童")
elif  age <= 18:
    print("少年")
elif  age <= 30:
    print("青年")
elif  age <= 40:
    print("壯年")
elif  age <= 50:
    print("中年")
elif  age <= 150:
    print("老年")
else:
    print("妖怪")
複製代碼

循環語句(while)

格式與邏輯

''' 格式: while 表達式: 語句 邏輯:當程序執行到while語句時,首先計算表達式的值,若是表達式的值爲假,則跳過整個while語句繼續向下執行。若是表達式的值爲真,則執行語句,執行完語句再計算表達式的值。若是表達式的值爲假,則跳過整個while語句繼續向下執行。若是表達式的值爲真,則執行語句,執行完語句在計算表達式的值,如此循環往復直到表達式的值爲假才中止。 '''

複製代碼

使用else語句

'''使用else語句 格式: while 表達式: 語句1 else: 語句2 邏輯:在表達式的值爲False時執行else語句中的語句2,若是是break結束的循環不走else語句 '''
a = 1
while a < 5:
    print("sunck is a nice man")
    a += 1
else:
    print("sunck is a good man")
複製代碼

循環語句(for)

格式與邏輯

''' 格式: for 變量 in 集合: 語句 邏輯:當程序執行到for語句時,按順序取「集合」中的每一個元素賦值給「變量」,在執行「語句」。如此循環往復,直到取完集合中的元素爲止。 '''
複製代碼

range函數

# range([startNum,]endNum[, step])
# 列表生成器
# startNum:開始的數字,默認爲0
# endNum:結束的數字,不包含在內
# step: 步長,默認爲1
# [1,2,3,4,5]
for x in range(1, 6):
    print("x = %d"%x)

複製代碼

同時遍歷下標和元素

# 同時遍歷下標和元素
for index, x in enumerate([1,2,3,4,5]):
    print(index, x)

複製代碼

pass語句、continue語句、break語句

pass語句

'''pass語句 做用:當語句要求不但願任何命令或代碼來執行 說明:pass語句時一個空操做,在執行時沒有任何響應。pass也是代碼最終會用的,可是暫時寫不出來 使用在 if語句、while語句、for語句、函數、類等位置 '''
if 1:
    pass
for x in [1,2,3]:
    pass

複製代碼

continue語句

'''continue 做用:跳過本次循環快中的剩餘語句,而後繼續下一次循環 注意:只能跳過距離最近的for或者while '''
for x in [1,2,3,4,5]:
    if x == 3:
        continue
    print("x = %d"%x)
print("-------------------")

# 代碼嵌套,層級要明確,嵌套最多在六、7層左右,最好3層
for m in [1,2,3,4,5]:
    print("m = %d"%m)
    for n in [1,2,3,4,5]:
        if n == 3:
            continue
        print("n = %d"%n)
複製代碼

break語句

'''break 做用:跳出循環 注意:只能跳出距離最近的for或者while '''
for x in [1,2,3,4,5]:
    if x == 3:
        break
    print("x = %d"%x)
# print("-------------------")
# for m in [1,2,3,4,5]:
# print("m = %d"%m)
# for n in [1,2,3,4,5]:
# if n == 3:
# break
# print("n = %d"%n)


# 循環語句能夠有else子句,表達式錯誤致使循環終止時被執行,但循環被break終止時else語句不執行
index = 0
while index < 3:
    print("index = %d"%index)
    index += 1
    if index == 1:
        break
else:
    print("循環結束了")


print("---------------------------------")
複製代碼

深拷貝與淺拷貝

from copy import copy, deepcopy
''' ==:判斷的是值 is:判斷的是內存地址 '''
# num1 = 300
# num2 = 300
# print(id(num1), id(num2))
# print(num1 == num2)
# print(num1 is num2)

''' 小整數對象:[-5, 256] 最好在python環境中演示,pycharm進行了其餘的優化 '''


# a = [1,2,3,4,5,[7,8,9]]
# b = a
# print(b == a)
# print(b is a)
# a[5][1] = 100
# print(a, b)
# print(id(a), id(b))
# print(id(a[5]), id(b[5]))

a = [1,2,3,[4,5,6]]
#深淺拷貝的區分的前提是列表中要有其餘列表
#淺拷貝:只拷貝表層元素
# copy
b = copy(a)


#深拷貝:在內存中從新建立全部子元素
# deepcopy
c = deepcopy(a)

a[0] = 100
print(a, b, c)

# print(b == a)
# print(b is a)
# print(c == a)
# print(c is a)
# print(id(a[1]), id(b[1]), id(c[1]))
# print(id(a), id(b), id(c))
# print(id(a[3]), id(b[3]), id(c[3]))
# print(id(a[3][1]), id(b[3][1]), id(c[3][1]))

複製代碼

turtle繪圖模塊

操做

''' 是一個簡單的繪圖工具 提供了一個小海龜,相似一個機器人,能聽懂一些簡單的命令 繪圖窗口的原點(0,0)在正中間,默認海龜向右側移動 '''



'''操做命令 一、運動命令 forward(a) 向前移動,a表明距離 backward(a) 向後移動,a表明距離 right(degree) 向右轉動degree度 left(degree) 向左轉動degree度 goto(x, y) 將筆畫(小海龜)移動到座標(x,y)的位置 speed([speed]) 筆畫繪製的速度,範圍在[0,10]之間的整數 二、筆畫控制命令 up() 筆畫擡起,移動時不繪製圖形 down() 筆畫落下,移動時繪製圖形 setheading(degree) 海龜的朝向,degree表明角度 reset() 恢復設置,清空窗口,重置turtle爲起始狀態 clear() 清空窗口 pensize(width) 筆畫的寬度 begin_fill() 開始填充 fillcolor(color) 繪製圖形的填充顏色 end_fill() 結束填充 dot(radius, color) 畫點 circle(redius, extent, steps) 繪製一個圓形,redius爲半徑,extent爲次數,若是是畫圓就沒必要寫第二個參數 三、其餘命令 undo() 撤銷turtle上一個動做 hideturtle() 隱藏箭頭 showturtle() 顯示箭頭 write(str, font=(font-name, font-size, font-type)) screensize(x,y) 設置屏幕的寬高 '''
複製代碼

Number(數字)

整數

''' 整數: python能夠處理任意大小的整數,包含負數 '''
num1 = 10
print(id(num1))
print(type(num1))
# 連續定義
num3 = num4 = num5 = 1
# 交互對稱定義
num6, num7 = 1, 2
print(num6, num7)

# 查看數據在內存中的地址
# 小整數對象
num1 = 12
num2 = 13
print(id(num1), id(num2))
num8 = -6
num9 = -6
print(id(num8), id(num9))
複製代碼

浮點數

''' 浮點:由整數部分和小數部分組成的 注意:運算可能有四捨五入的偏差 '''
num10 = 0.1
num11 = 0.2
print(num10 + num11)

複製代碼

複數

''' 複數:實數部分和虛數部分構成,通常不使用。 '''

複製代碼

數學函數

# 求絕對值
num1 = -18
num2 = abs(num1)
print(num2)

# 求多個數中的最大值
print(max(5,3,2,8,6,9,11,3,7))

# 求多個數中的最小值
print(min(5,3,2,8,6,9,11,3,7))

# 求x的n次方
print(pow(2, 4))

# 四捨五入 
# round(x[, n])將浮點數進行四捨五入,若是給出n的值,則表明舍入到小數點的後四位
print(round(3.1415926, 4))

複製代碼

math模塊

import math
# 向上取整 18.9
print(math.ceil(18.1))
# 向下取整
print(math.floor(18.9))
# 獲得浮點數的小數部分和整數部分
print(math.modf(18.5))
# 開平方,數字不能是負數
print(math.sqrt(5))

複製代碼

隨機數

# 導入隨機數模塊
import random

複製代碼
# 一、choice(seq) 從序列(集合)中隨機獲取一個元素
print(random.choice([2,4,6,8,10]))

複製代碼
# 二、randrange([start, ]stop[, step])
# 做用:從指定範圍內,按照指定基數遞增的集合中獲取一個隨機數,基數默認爲1
# start-指定範圍的開始值,包含在範圍內,默認從0開始
# stop-指定範圍的結束值,不包含在範圍內
# step-指定的基數
print(random.randrange(3)) #[1,2,3,4]

複製代碼
# 三、random()
# 隨機生成一個實數,範圍在[0, 1)之間,獲得浮點數
print(random.random())

複製代碼
# 四、uniform(x, y)
# 隨機生成一個實數,範圍在[x, y]之間,獲得浮點數,x爲隨機數的最小值,y爲隨時的最大值
print(random.uniform(3, 8))

複製代碼
# 五、shuffle(list)
# 將序列的元素隨機排列
arr = [1,2,3,4,5]
random.shuffle(arr)
print(arr)

複製代碼
# 六、randint(start, stop)
# 在指定的範圍得到一個整數[start, stop]
print(random.randint(1,5))
複製代碼

三角函數

三角函數

#反正弦弧度值
asin(x)
#反正切弧度值
atan(x)
#反餘弦弧度值
acos(x)
#x的弧度的餘弦值
cos(x)
#x的弧度的正弦值
sin(x)
#x的弧度的正切值
tan(x)
#角度轉爲弧度
radians(x)
複製代碼

數字類型轉換

# int(x) 將x轉爲一個整數
print(int(10.1))
print(int("123"))

複製代碼
# float(x)
print(float(10))
print(float("123.34"))

複製代碼

字符串

什麼是字符串

''' 什麼是字符串? 字符串是以單引號或者雙引號括起來的任意文本,好比'sunck is a good man'或者"sunck is a nice man"。可是要注意引號自己是一種表現形式,不屬於字符串的一部分。 注意:若是字符串自己帶雙引號 'sunck is a "very" good man' '''

複製代碼

建立字符串

#建立字符串
str1 = 'sunck is a good man'
str2 = "sunck is a nice man"

複製代碼

字符串運算

'''字符串運算'''
# 字符串拼接
str3 = 'sunck is a good man'
str4 = "sunck is a nice man"
print(str3 + str4)
#重複輸出字符串
print(str3 * 3)
# 經過索引下標獲取字符串中的字符,索引從0開始(程序員放羊) str[index]
print(str3[1])
# 截取字符串中的一部分 切片編程
print("*"+str3[11:15]+"*")
print("*"+str3[11:]+"*")
print("*"+str3[:15]+"*")
# 判斷字符串中是否存在某些內容
print("kaige" in str3)
複製代碼

格式化輸出字符串

''' 格式化輸出(佔位符) %s 格式化字符串 %d 格式化整數 %f 格式化浮點數,能夠指定小數點後的精度,默認保留小數點後6位 '''
name = "sunck"
age = 18
height = 173.5
# sunck is a good man, he is 18 years old, his height is 173.5cm.
print(name, "is a good man, he is", age, "years old, his height is", height, "cm.")
#若是隻有一個替換,能夠不寫%後面的小括號,可是建議仍是不要省略
print("%s is a good man, he is %d years old, his height is %.2fcm."%(name, age, height))
weight=75
print("*%d*"%(weight))
print("*%5d*"%(weight))
print("*%-5d*"%(weight))
print("*%.5d*"%(weight))
複製代碼

經常使用轉義字符

''' 經常使用轉義字符 反斜槓 \\ 單引號 \'
雙引號     \" 換行 \n 橫向製表符 \t ''' str5 = '\\' print(str5) str6 = "sunck is a \"very\" good man"
print(str6)
print("sunck is\na good man")
# 若是字符串內部有過個換行,用\n寫在一行裏很是利於閱讀
print("sunck\nis\na\ngood\nman")
print(''' line1 line2 line3 line4 ''')
print("sunck\tgood")
# 若是字符串裏面有不少字符須要轉義,就須要加入不少\,爲了簡化,python容許使用r''表示''內部的字符串默認不轉義
print('\\\t\\')
print(r'\\\t\\')
複製代碼

String內置函數

# eval()
''' 原型:eval(*args, **kwargs) 功能:將字符串當成有效的表達式來求值並返回計算結果 參數: '''
num1 = eval("123")
print(num1)
print(type(num1))
print(eval("+123"))
print(eval("-123"))
print(eval("12+3"))
print(eval("12-3"))
# print(eval("a123"))
# print(eval("12a3"))
abc = "123"
print(eval("abc"))
複製代碼
# len(string)
''' 原型: 功能:返回字符串的長度(按字符個數計算) 參數: '''
print(len("sunck is a good man"))
print(len("sunck is a good man凱"))
複製代碼
# lower()
''' 原型: 功能:轉換字符串中全部的大寫字母爲小寫 參數: '''
str1 = "Sunck Is A Good maN"
str2 = str1.lower()
print(str1, str2)
複製代碼
# upper()
''' 原型: 功能:轉換字符串中全部的小寫字母爲大寫 參數: '''
複製代碼
# swapcase()
''' 原型: 功能:將字符串中大寫轉爲小寫,小寫轉爲大寫 參數: '''
str3 = "Sunck Is A Good maN"
str4 = str3.swapcase()
print(str3, str4)
複製代碼
# capitalize()
''' 原型: 功能:將字符串中第一個字符轉爲大寫,其他轉爲小寫,用於每句話中開始字母大寫 參數: '''
str5 = "sunck Is A Good maN"
str6 = str5.capitalize()
print(str5, str6)
複製代碼
# title()
''' 原型: 功能:獲得「標題化」的字符串,每一個單詞的首字符大寫,其他小寫 參數: '''
str7 = "sunck Is A Good maN"
str8 = str7.title()
print(str7, str8)
複製代碼
# center(width[, fillchar])
''' 原型: 功能:返回一個指定寬度width的居中字符串,fillchar爲填充字符,默認爲空格 參數: '''
str9 = "good"
str10 = str9.center(20, "#")
print("*"+str10+"*")

複製代碼
# ljust(width[, fillchar])
''' 原型: 功能:返回一個指定寬度width的左對齊字符串,fillchar爲填充字符,默認爲空格 參數: '''
str11 = "good"
str12 = str11.ljust(20, "#")
print("*"+str12+"*")

複製代碼
# rjust(width,[, fillchar])
''' 原型: 功能:返回一個指定寬度width的右對齊字符串,fillchar爲填充字符,默認爲空格 參數: '''

複製代碼
# zfill (width)
''' 原型: 功能:返回指定寬度width的右對齊字符串,填充0 參數: '''
str13 = "good"
str14 = str13.zfill(20)
print("*"+str14+"*")


複製代碼
# count(str[, beg= 0,end=len(string)])
''' 原型: 功能:返回str在string裏面出現的次數,若是beg或者end指定則返回指定範圍內str出現的次數 參數: '''
str15 = "sunck"
str16 = "sunck is a good man! sunck is a nice man"
print(str16.count(str15,0,20))

複製代碼
# find(str[, beg=0 end=len(string)])
''' 原型: 功能:檢測str是否包含在string中,若是指定beg和end,則檢測指定範圍內是否包含。若是包含返回第一個開始的索引值,不然返回-1 參數: '''
str17 = "sunck"
str18 = "cool"
str19 = "aaasunck is a good man! sunck is a nice man"
res = str19.find(str18)
print(res)

複製代碼
# index(str[, beg=0, end=len(string)])
''' 原型: 功能:跟find()同樣,區別在於若是str不存在會報異常 參數: '''
str20 = "sunck"
str21 = "cool"
str22 = "aaasunck is a good man! sunck is a nice man"
res = str22.index(str20)
print(res)

複製代碼
# rfind(str[, beg=0,end=len(string)])
''' 原型: 功能:相似於find(),只不過從右邊開始查找 參數: '''

複製代碼
# rindex(str[, beg=0, end=len(string)])
''' 原型: 功能:相似於index(),只不過從右邊開始查找 參數: '''


複製代碼
# lstrip()
''' 原型: 功能:截掉字符串左邊指定的字符,默認爲空格 參數: '''
str23 = " sunck is a good man"
str24 = str23.lstrip()
print(str23)
print(str24)
str25 = "*****sunck is a good man"
str26 = str25.lstrip("*")
print(str25)
print(str26)


複製代碼
# rstrip()
''' 原型: 功能:截掉字符串右邊指定的字符,默認爲空格 參數: '''


複製代碼
# strip([chars])
''' 原型: 功能:在字符串上執行lstrip和rstrip 參數: '''
str27 = "*****sunck is a good man**"
str28 = str27.strip("*")
print(str27)
print(str28)


複製代碼
# split(str="", num=string.count(str))
''' 原型: 功能: 參數: '''
str29 = "sunck#is#a#good#man"
wordList = str29.split("#")
print(wordList)
print(type(wordList))

複製代碼
# splitlines([keepends])
''' 原型: 功能:按照行('\r','\r\n','\n'),若是keepends爲False,不包含換行符,不然保留換行符 參數: '''
str30 = '''good nice cool handsome '''
wordList2 = str30.splitlines()
print(wordList2)

複製代碼
# join(seq)
str31 = " ".join(wordList)
print(str31)
''' 原型: 功能: 參數: '''

複製代碼
# max(str)
''' 原型: 功能:返回字符串中最大的字母 參數: '''
str32 = "sunck is a good man"
print(max(str32))

複製代碼
# min(str)
''' 原型: 功能:返回字符串中最小的字母 參數: '''


複製代碼
# replace(old, new [, max])
''' 原型: 功能:將字符串中的old替換成new,若是max指定,則替換不超過max次 參數: '''
str33 = "sunck is a good man, sunck is a nice man, sunck is a cool man"
str34 = str33.replace("sunck", "kaige")
print(str34)


複製代碼
# maketrans()
''' 原型: 功能:建立字符映射的轉換表,對於接受兩個參數的,第一個是字符串,表示要轉換的字符,第二個也是字符串表示轉換的目標 參數: '''
t = str.maketrans("ag", "12")



複製代碼
# translate(table)
''' 原型: 功能:根據str給出的錶轉換字符串 參數: '''
str35 = "sunck is a good manag"
print(str35.translate(t))



複製代碼
# isalpha()
''' 原型: 功能:若是字符串至少有一個字符而且全部的字符都是字母返回True,不然返回假 參數: '''
print("".isalpha())
print("abc".isalpha())
print("abc12".isalpha())



複製代碼
# isalnum()
''' 原型: 功能:若是字符串至少有一個字符而且全部的字符都是字母或數字返回True,不然返回假 參數: '''
print("".isalnum())
print("abc".isalnum())
print("abc12".isalnum())



複製代碼
# isupper()
''' 原型: 功能:若是字符串至少有一個字符而且全部的字母都是大寫字母返回True,不然返回假 參數: '''
print("sunck".isupper())
print("SUNCK".isupper())
print("SUNCK#$%".isupper())
print("SUNCK123".isupper())
print("".isupper())



複製代碼
# islower()
''' 原型: 功能:若是字符串至少有一個字符而且全部的字母都是小寫字母返回True,不然返回假 參數: '''



複製代碼
# istitle()
''' 原型: 功能:若是字符串是標題化的返回True,不然返回False 參數: '''



複製代碼
# isdigit()
''' 原型: 功能:若是字符串只包含數字返回True,不然返回False 參數: '''
print("".isdigit())
print("123".isdigit())
print("abc123".isdigit())



複製代碼
# isnumeric()
''' 原型: 功能:若是字符串只包含數字返回True,不然返回False 參數: '''



複製代碼
# isdecimal()
''' 原型: 功能:檢測字符串是否只包含十進制數字 參數: '''



複製代碼
# isspace()
''' 原型: 功能:若是字符串中只含有空格則返回True,不然返回False 參數: '''
print("".isspace())
print(" ".isspace())
print(" a".isspace())
print("\t".isspace())
print("\n".isspace())

print("--------------------")



複製代碼
# startswith(str[, beg=0,end=len(string)])
''' 原型: 功能:檢查字符串是否以str開頭,是則返回True, 不然返回False。若是指定了beg和gend,則在指定範圍內檢查 參數: '''
str40 = "sunck is a good man"
print(str40.startswith("good"))



複製代碼
# endswith(suffix[, beg=0, end=len(string)])
''' 原型: 功能:檢查字符串是否以suffix結尾,是則返回True, 不然返回False。若是指定了beg和gend,則在指定範圍內檢查 參數: '''


複製代碼
# encode(encoding='UTF-8',errors='strict')
''' 原型: 功能:以encoding指定的編碼格式進行編碼,若是出錯默認報一個ValueError異常,除非errors指定的是igonre或者replace 參數: '''
str41 = "凱哥是一個好男人"
str42 = str41.encode()
str43 = str41.encode("GBK") #gb2312
print(str41)
print(str42)
print(str43)


複製代碼
# bytes.decode(encoding="utf-8", errors="strict")
''' 原型: 功能:解碼 參數: '''
print(str42.decode("utf-8"))
print(str43.decode("GBK"))


複製代碼
# ord()
''' 原型: 功能:獲取字符的整數表示 參數: '''
print(ord("A"))
print(ord("凱"))


複製代碼
# chr()
''' 原型: 功能:把數字編碼轉爲對應的字符 參數: '''
print(chr(65))
print(chr(20975))



複製代碼
# str()
''' 原型: 功能:轉成字符串 參數: '''
print(str(123))
print(str(123.1))
print(type(str(True)))



複製代碼

布爾值和None

做用:做爲真假的判斷
''' b = True c = False print(b, c) print(type(b), type(c)) 複製代碼
''' 空值:是python裏一個特殊的值,用None表示。None不能理解爲0,由於0是有意義的,而None是一個特殊的控制,沒有實際意義。 做用:定義個變量時,不知道初始值要賦值成什麼,那麼就賦值爲None,當有肯定值在進行賦值操做。 '''
d = None
print(d)
print(type(d))


複製代碼

list列表

概述

''' 問題:存儲5我的的年齡,求他們的平均年齡 '''
age1 = 18
age2 = 19
age3 = 20
age4 = 21
age5 = 22
print((age1+age2+age3+age4+age5)/5)

''' 問題:存儲100我的的年齡,求他們的平均年齡 解決:使用列表 列表本質:是一種有序的集合 '''


複製代碼

建立列表

'''建立列表 格式: 列表名 = [列表選項1, 列表選項2, ……, 列表選項n] '''
# 建立空列表
list1 = []

# 建立帶有元素的列表
# 列表中的元素的數據類型能夠不一樣
list2 = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, "good", True, None]


複製代碼

列表元素訪問

''' 列表元素的訪問 '''
list3 = [18, 19, 20, 21, 22]
# 取值:列表名[下標]
print(list3[2])
# 替換:列表名[下標] = 新值
list3[2] = 200
print(list3)
# 注意:下標不要越界
# print(list3[5])
# list3[5] = 23
# print(list3)


複製代碼

列表操做

''' 列表操做 '''
# 列表組合
list4 = [1,2,3]
list5 = [4,5,6]
print(list4, list5)
print(list4 + list5)
# 列表重複
list6 = [7,8,9]
print(list6 * 3)
# in not in
print(1 in [1,2,3])
# 列表截取(切片)
list7 = [1,2,3,4,5,6,7,8,9,0]
print(list7[2])
print(list7[1:4])
# -1表示的是最後一個元素的下標, -2倒數第二個元素的下標
print(list7[1:-1])
print(list7[4:])
print(list7[:4])

複製代碼

二維列表

''' 二維列表:列表中元素是一維列表 本質:一維列表 '''
list8 = [[1,2,3],
         [4,5,6],
         [7,8,9]]
print(list8)
print(list8[1][1])

複製代碼

列表方法

# append(obj)
# 在列表的末尾添加一個新的元素
list1 = [1,2,3,4,5]
list1.append([9,8,7])
print(list1)

複製代碼
# extend(seq)
# 在列表末尾一次性追加多個元素
list2 = [1,2,3,4,5]
list2.extend([9,8,7])
print(list2)


複製代碼
# insert(index, obj)
# 將元素出入列表,不會覆蓋原元素,原元素按順序後移
list3 = [1,2,3,4,5]
list3.insert(2, 100)
print(list3)


複製代碼
# pop(obj=list[-1])
# 移除列表中指定下標處的元素,默認刪除最後一個元素
list4 = [1,2,3,4,5]
list4.pop()
# list4.pop()
print(list4)


複製代碼
# remove(obj)
# 移除列表中的某個值的第一個匹配項
list5 = [1,2,3,4,5,3]
list5.remove(3)
print(list5)


複製代碼
# clear()
# 清空列表
list6 = [1,2,3,4,5,3]
list6.clear()
print(list6)


複製代碼
# index(obj)
# 從列表中找出某個值第一個匹配項的下標
list6 = [1,2,3,4,5,3]
print(list6.index(3))


複製代碼
# len(list)
# 返回列表中元素的個數
list7 = [1,2,3,4,5,3]
print(len(list7))


複製代碼
# count(obj)
# 統計某個元素在列表中出現的次數
list7 = [1,2,3,4,5,3]
print(list7.count(3))


複製代碼
# max(list)
# 返回列表中元素的最大值


複製代碼
# min(list)
# 返回列表中元素的最小值


複製代碼
# reverse()
# 倒序列表中元素
list8 = [1,2,3,4,5,3]
list8.reverse()
print(list8)


複製代碼
# sort([func])
list9 = [4,7,1,3,9,5]
list9.sort()
list9.reverse()
print(list9)


複製代碼
# list(seq)
# 轉爲列表 字符串、元組、集合
print(list("sunck"))


複製代碼

tuple(元組)

概述

''' 元組 本質:是一種有序集合 特性: 一、與列表很是相似 二、一旦初始化就不能修改 三、使用小括號 '''


複製代碼

建立元組

#建立元組: 元組名 = (元組選項1, 元組選項2, ……, 元組選項n)
#建立空元組
t1 = ()
print(t1)
# 定義帶元素的元組
# 元素類型能夠不一樣
t2 = (1,2,3,4,5,"good")
print(t2)
# 定義含有一個元素的元組
# 注意:加個逗號
t3 = (1,)
print(t3)

複製代碼

元組的訪問

''' 元組元素的訪問 '''
#取值 元組名[下標]
t4 = (1,2,3,4,5)
print(t4[1])
# print(t4[5]) #下標越界
print(t4[-1])
print(t4[-5])
# print(t4[-6]) # 下標越界
#修改元組,元組的元素不能修改,可是元素若是是個列表那麼能夠修改這個列表
t5 = (1,2,3,4,5,[6,7,8])
# t5[5] = [8,7,6]
t5[5][1] = 100
print(t5)

複製代碼

元組的操做

'''元組的操做'''
#元祖的組合
t6 = (1,2,3)
t7 = (4,5,6)
print(t6 + t7)
#元組重複
print(t6 * 3)
# 元組截取(切片)
# 與列表、字符串向相似
t8 = (1,2,3,4,5,6,7,8,9)
print(t8[2:7])


複製代碼

元組方法

'''元組的方法'''
# len(tuple)
# 返回元組的元素個數
t9 = (1,2,3)
print(len(t9))

# max(tuple)
# min(tuple)

# tuple(seq)
# 將集合轉爲元組
l = [1,2,3,4,5,6]
t10 = tuple(l)
print(t10)


複製代碼

dict(字典)

概述

''' 使用鍵-值對(key-value)的形式存儲數據,具備極快的查找速度 能夠的特性: 一、字典中的key必須惟一 二、key必須是不可變對象 a、字符串、整數等都是不可變的,能夠做爲key b、列表時可變的,不能做爲key 三、key通常爲字符串 思考:保存一個學生的基本信息(姓名、性別、年齡、升高、體重) stu1 = ["sunck", "男", 18, 173.5, 75] stu2 = ["男", "liudehua", 72, 55, 173] 解決:使用字典 注意:字典中的鍵值對是無序的 '''


複製代碼

建立字典

# 建立字典存儲一個學生的基本信息
# {key1:value,key2:value2,……,keyn:valuen}
stu1 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
stu2 = {"name": "liudehua", "age": 55, "sex": "男", "height": 173, "weight": 72}
stus = [stu1, stu2]
print(stu1)


複製代碼

訪問字典

#元素的訪問
stu3 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
#獲取 字典名[key] 字典.get(key)
print(stu3["name"])
# print(stu3["score"]) #獲取的鍵不存在會報錯
score = stu3.get("score")
if score:
    print("分數爲:%.2f"%score)
else:
    print("學生沒有這個屬性")


複製代碼

字典的添加、刪除、遍歷

#添加 若是鍵不存在則增長屬性,不然覆蓋原數據
stu3["socre"] = 99.99
stu3["height"] = 180
print(stu3)


複製代碼
#刪除
stu3.pop("socre")
print(stu3)


複製代碼
#遍歷
stu4 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
for key in stu4:
    print(key)
print("--------")
for value in stu4.values():
    print(value)
print("--------")
for key, value in stu4.items():
    print(key+": "+str(value))
print("--------")
for index, key in enumerate(stu3):
    print(index, key)


複製代碼

list和dict的比較

'''比較list和dict dict 優勢:查找和插入的速度極快,不會隨着key的增多而下降效率 缺點:須要佔用大量的內存,內存浪費過多 list 優勢:佔用內存空間小,浪費內存不多 缺點:查找和插入的時間會隨着元素的增長而增長 '''


複製代碼

set(集合)

概述

''' 與dict相似,是一組key的集合(不存儲value) 本質:無序和無重複的集合 '''


複製代碼

建立

#建立:須要用一個list或者tuple做爲輸入集合
# 注意列表中的重複元素會被過濾掉
s1 = set([1,2,3,4,5,3,4])
print(s1)
# 列表去重
numList = [1,2,3,5,7,8,3,5,6,8,9]
numList = list(set(numList))
print(numList)


複製代碼

添加

#添加
s2 = set([1,2,3,4,5])
# 插入list、字符串、元組的每一個元素
# iterable 可迭代對象
# s2.update("sunck")
# s2.update([6,7,8])
# s2.update((6,7,8))
# 不能直接插入數字
# s2.update(9)
print(s2)


複製代碼

刪除

#刪除
s3 = set([1,2,3,4,5])
# 從左側開始刪除
print(s3.pop())
# 刪除對應的元素,若是元素不存在會報KeyError的異常
s3.remove(3)
print(s3)


複製代碼

遍歷

#遍歷
s4 = set([6,2,3,4,5])
for key in s4:
    print(key)
print("------")
for index, key in enumerate(s4):
    print(index, key)


複製代碼

交集與並集

#交集與並集
s5 = set([1,2,3])
s6 = set([2,4,3])
# 交集
print(s5 & s6)
# 並集
print(s5 | s6)


複製代碼

類型轉換

''' list和tuple中的元素不能存在可變對象 list、tuple、string-->set set() tuple、set、string-->list list() list、set、string-->tuple tuple() '''

複製代碼

函數

概述

'''認識函數: 在一個完整的項目中,某些代碼會被反覆使用。那麼將某段代碼封裝成函數,當咱們要使用功能的時候直接調用函數便可 本質:函數是對功能的封裝 有點:簡化代碼結構,增長代碼的複用度 '''

複製代碼

定義函數

'''定義函數 格式 def 函數名(參數列表): 語句 return 表達式 說明: def:函數代碼塊以def關鍵字開頭 函數名:遵照標識符的規則 ():參數列表的開始和結束 參數列表:是函數的調用者給函數的信息,多個信息之間用逗號分隔,若是沒有信息,那麼小括號中什麼都不用寫(注意此時小括號不能省略)(形參) 冒號:函數的內容以冒號起始,而且鎖緊 語句:函數封裝的功能 return:通常用於結束函數,並返回給函數的調用者一些信息。「表達式」就是要返回的數據。若是沒有顯示的去寫return語句,默認return回None 注意: 定義函數時,程序是不會執行函數,當調用函數時纔會執行 '''

# def gaolei(money):
# pass

複製代碼

使用函數

'''使用函數 格式: 函數名(參數列表) 說明: 函數名:要使用某個功能函數的名字 ():參數列表的開始和結束 參數列表:調用者給函數的信息(實參) 函數調用的本質:實參給形參賦值的過程 '''

複製代碼

函數參數

# 編寫函數,給函數一個名字,一個年齡,一些愛好,在函數中進行打印
# sunck 18 pwoer、money、book

#形式參數(形參):變量
#參數的數量理論上是無限制的,可是實際中最好不要超過六、7個,參數是類型沒有限制
def func(name, age, hobby):
    print("%s is a good man! he is %d years old! he like %s、%s and %s"%(name, age, hobby[0], hobby[1], hobby[2]))

#函數在調用時,須要給函數按順序傳遞數據,數量要對應
# 實際參數(實參):是值
func("sunck", 18, ["power", "money", "book"])

複製代碼

函數返回值

# 編寫函數,實現計算兩個數的和
# 注意:在定義的函數體中,儘可能不要常出現print和input
def func(x, y):
    sum = x + y
    return sum #將結果返回到調用函數的位置,返回的數據能夠是任意類型的數據

# res接收了func函數運算後的返回值
res = func(1, 2)

複製代碼

傳遞參數

# 值傳遞:傳遞不可變類型數據
def func(num):
    print(id(num))
    num = 10
    print(id(num))
a = 20
print(id(a))
func(a)
print(a)




print("-------------------")
# 引用傳遞:傳遞可變類型數據
# 本質仍是值傳遞,傳遞的是地址
def func2(arr):
    print(id(arr))
    arr.pop()
    print(id(arr))
li = [1,2,3,4,5]
print(id(li))
func2(li)
print(id(li))
print(li)
複製代碼

關鍵字參數

# -*- coding:utf-8 -*-



#目前爲止的要求:函數調用時參數的順序要與定義時一致
#關鍵字參數:容許函數調用時參數的順序與定義時不一致


def func(name, age):
    print("%s is a good man! he is %d years old!"%(name, age))

#使用關鍵字參數
func(age=18, name="sunck")
複製代碼

默認參數

# -*- coding:utf-8 -*-

# 使用默認參數
# 在定義函數時儘可能將默認參數寫在最後
def func(name, age=18):
    print("%s is a good man! he is %d years old!"%(name, age))

# 在調用函數時,若是沒有傳遞參數,就使用默認參數的值
func("sunck", 20)

複製代碼

不定長參數

# -*- coding:utf-8 -*-


#不定長參數:能處理比當初定義時更多的參數

# 在變量前加了星號,變量會存放全部未命名的變量的參數,若是在函數調用時沒有指定參數,他就是個空元組
# 不定長參數在默認參數後面
# def func(name, age, a = 10, *args):
# print("%s is a good man! he is %d years old"%(name, age))
# print(args, type(args))
#
# func("sunck", 18)


# **kwargs
# **表明着鍵值對字典,和*差很少
# def func(name, age, **kwargs):
# print("%s is a good man! he is %d years old"%(name, age))
# print(kwargs, type(kwargs))
#
# func("sunck", 18, x=1, y=2, z=3)


def func(*args, **kwargs):
    print(args)
    print(kwargs)

func(1,2,3,x=1,y=2,z=3)

複製代碼

多個返回值

# -*- coding:utf-8 -*-


# 返回值能夠一次性返回多個值
# 遊戲中返回任務的座標
def func():
    return 1,2

x, y = func()
z = func()
print(x, y)
print(z)
# for index, value in enumerate([1,2,3,4,5]):

複製代碼

匿名函數

# -*- coding:utf-8 -*-





''' 概念:不在使用def語句這樣標準的形式定義函數,使用lambda來建立匿名函數 特定: 一、lambda只是一個表達式,函數體比def簡單得多 二、lambda主體是一個表達式而不是代碼塊,僅能在lambda表達式中封裝有限的邏輯 三、lambda函數擁有本身的命名空間,且不能訪問自有參數序列以外或全局命名空間裏的參數 四、雖然lambda函數看起來只能寫一行,去不一樣於c和c++的內聯函數,後者的目的是調用小函數時不佔用棧內存而增長運行效率 格式: lambda [arg1[, arg2[, arg3, ……]]]:expression 使用:做爲參數傳遞,實現回調。簡化代碼 '''

f = lambda x, y: x + y
ret = f(5, 6)
print(ret)

複製代碼

特殊函數

map函數

'''map(fn, lsd) 參數: fn:是一個函數 lsd:集合 功能:將傳輸的函數fn依次做用到lsd集合中的每一個元素,並把結果做爲新的Iterator返回 '''
def chr2int(chr):
    return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
ret = map(chr2int, "13586")
print(ret)
print(list(ret))

複製代碼

reduce函數

'''reduce(fn, lsd) 參數: fn:函數 lsd:集合 功能:傳入的fn函數做用在lsd集合中,這個fn函數必須接受兩個參數,reduce把結果繼續和序列的下一個元素做累計計算 reduce(f, [a, b, c, d])==f(f(f(a,b),c),d) '''
# 求一個序列的和
from functools import reduce
def func(x, y):
    return x + y
res = reduce(func, [1,2,3,4,5])
print(res)



#reduce配合map實現str2int
def str2int(s):
    def chrToint(chr):
        return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
    def f(x, y):
        return x * 10 + y
    return reduce(f, map(chrToint, s))

res = str2int("13543")
print(res)
print(type(res))

複製代碼

filter函數

# -*- coding:utf-8 -*-



''' filter(fn, lsd) 參數: fn:函數 lsd:集合 功能:用於過濾序列,把傳入的fn函數依次做用在lsd集合中的每一個元素上,而後根據返回值是True仍是False決定是否保留該元素 '''

li1 = [1,2,3,4,5,6,7,8,9]
# 去掉列表中的全部偶數

#過濾的過程
# for i in li1:
# if i % 2 == 0:
# li1.remove(i)
# print(li1)

#過濾的邏輯
def func(num):
    if num % 2 == 0:
        return False
    return True
res = filter(func, li1)
print(li1)
print(res)
print(list(res))





# 找全部的素數



# 需求:刪除列表中是空字符串的元素
li2 = ["a", "", "", "c", " ", " bsg "]
def f(item):
    return item and item.strip()
res = filter(f, li2)
print(list(res))

複製代碼

sorted函數

# -*- coding:utf-8 -*-


''' 排序算符:冒泡排序、快速排序、 選擇排序、計數器排序…… '''
li = [3,4,1,2,5]


# 對列表進行排序
li1 = [3,4,1,2,5]
li2 = sorted(li1)
print(li2)

# 按絕對值大小排序
li3 = [3,-4,1,-2,5]
# key接收函數來實現自定義的排序
li4 = sorted(li3, key=abs)
print(li4)


#降序排序
li5 = [3,-4,1,-2,5]
li6 = sorted(li5, reverse=True)
print(li6)


# 字符串大小問題
# 原理:獲取兩個字符的第一個字符進行比較,誰的ASCII值大那麼誰就大,若是相同則獲取下一位字符比較
# print("abc">"ab")
li7 = ["abc", "awg", "agaerger", "eherth"]
#自定義排序邏輯
def func(x):
    return len(x)
li8 = sorted(li7, key=func)
print(li8)

複製代碼

做用域

概述

# -*- coding:utf-8 -*-

''' 做用域:變量能夠使用的範圍,程序的變量並非在哪一個位置均可以訪問的,訪問的權限決定於這個變量實在哪裏賦值的。 做用域的劃分: 一、局部做用域(L) 二、閉包函數外到函數中(E) 三、全局做用域(G) 四、內建做用域(B) 變量查找規則: L->E->G->B,首先在自身做用域中查找,找不到的話依次向上級做用中查找,注意不會向低級做用域中查找 Python中只有模塊,類以及函數纔會引入新的做用域,其它的代碼塊(好比if、elif、else、for、while、try、except等)是不會引入新的做用域的。 '''
複製代碼

體現做用域

# -*- coding:utf-8 -*-
num = 5
#if不會引入新的做用域
if 1:
    index = 10
    print("num = %d"%num)

print("index = %d"%index)

def func(x, y):
    # 取值的使用
    print("在func中使用num:%d"%num)
    # 定義局部變量
    tmp = 100
    return x + y
print(func(1,2))
#在全局中使用局部變量,找不到的
# print("tmp = %d"%tmp)
複製代碼

修改全局變量

# -*- coding:utf-8 -*-



num = 10
def func():
    # 在函數的內部能夠直接獲取全局變量的值,可是不能直接修改全局變量的值。直接修改至關於定義一個新的局部變量,沒有修改到全局變量自己
    # 須要將定義的變量聲明成全局變量
    global num
    num = 2
    print("1-----num = %d" % num)

func()
print("2-----num = %d" % num)
複製代碼

修改嵌套做用域中的變量

# -*- coding:utf-8 -*-
a = 30
def func():
    # 有global會在nonlocal那裏報錯,申明爲全局的後就沒有嵌套的了
    # global a
    # a = 10
    def f():
        #想修改嵌套做用域中的變量,須要將它聲明
        # nonlocal a
        # a = 20
        print("1----a = %d"%a)
    f()
    print("2----a = %d"%a)

func()
print("3----a = %d"%a)

複製代碼

變量的做用域

# -*- coding:utf-8 -*-

a = 10
def func1():
    b = 20
    def func2():
        c = 30
        return a + b + c
    return func2()


print(func1())

複製代碼

利用閉包突破做用域鏈

# -*- coding:utf-8 -*-


'''閉包 概念:在函數體重定義內部函數,而且使用了外部函數的變量,而後把內部函數給,那麼這個內部函數就是閉包 優勢:避免污染全局環境,這樣就能夠在函數體外使用函數體中定義的變量 缺點:數據長期駐留在內存中,形成內存極大的浪費。 '''
a = 10
def func1():
    b = 20
    def func2():
        c = 30
        return a
    return func2


f2 = func1()
print(f2())





def func3():
    b = 40
    def func4():
        return b
    return func4

複製代碼

裝飾器

概念

# -*- coding:utf-8 -*-

''' 是一個閉包,把一個函數做爲參數而後返回一個替代版函數,本質上就是一個返回函數的函數 '''

#在不修改原函數的前提下增長函數的功能,最好的方式是使用裝飾器
def func():
    print("sunck is a good man")


def f():
    print("***********")
    func()

複製代碼

簡單裝飾器

# -*- coding:utf-8 -*-

def func():
    print("sunck is a good man")

def wrapper(f):
    def inner():
        print("***********")
        f()
    return inner

# d = wrapper(func)
# d()
func = wrapper(func)
func()

複製代碼

複雜裝飾器

# -*- coding:utf-8 -*-

# 下不修改say原函數代碼的狀況下增長say的功能,判斷age是否符合常理
def say(name, age):
    return "%s is a good man! he is %d years old"%(name, age)



def wrapper(f):
    def inner(name, age):
        #增長功能
        if age <= 0:
            age = 0
        return f(name, age)
    return inner


say = wrapper(say)

print(say("sunck", -18))
複製代碼

使用@符號裝飾

# -*- coding:utf-8 -*-
''' python2.4支持使用@將裝飾器應用在函數上,只須要再函數定義前加上@裝飾器的名稱便可 '''
def wrapper(f):
    def inner(name, age):
        #增長功能
        if age <= 0:
            age = 0
        return f(name, age)
    return inner

@wrapper
def say(name, age):
    return "%s is a good man! he is %d years old"%(name, age)

# 至關於 say = wrapper(say)

print(say("sunck", -18))
複製代碼

通用裝飾器

# -*- coding:utf-8 -*-

def wrapper(f):
    def inner(*args, **kwargs):
        #在這增長功能
        print("no zuo no die")
        res = f(*args, **kwargs)
        #若是要修改原函數的返回值,在這修改
        return res
    return inner



@wrapper
def func(name, age):
    print(name, age)
    return "sunck is a good man"

print(func("kaige", 17))

@wrapper
def func2(height):
    print(height)
    print("**********")
func2(111)

複製代碼

參數裝飾器

# -*- coding:utf-8 -*-

def wrapper(count=3):
    def deco(f):
        def inner(*args, **kwargs):
            for i in range(count):
                f(*args, **kwargs)
        return inner
    return deco

@wrapper()
def func():
    print("sunck is a good man")

func()

複製代碼

多個裝飾器

# -*- coding:utf-8 -*-
def wrapper1(f):
    print("enter wrapper1")
    def inner1(*args, **kwargs):
        print("enter inner1")
        res = f(*args, **kwargs)
        print("exit inner1")
        return res
    print("exit wrapper1")
    return inner1

def wrapper2(f):
    print("enter wrapper2")
    def inner2(*args, **kwargs):
        print("enter inner2")
        res = f(*args, **kwargs)
        print("exit inner2")
        return res
    print("exit wrapper2")
    return inner2

def wrapper3(f):
    print("enter wrapper3")
    def inner3(*args, **kwargs):
        print("enter inner3")
        res = f(*args, **kwargs)
        print("exit inner3")
        return res
    print("exit wrapper3")
    return inner3

''' 裝飾時:從距離近的裝飾器開始裝飾 執行時:從距離遠的裝飾器內部函數開始執行 '''
@wrapper1
@wrapper2
@wrapper3
def func(x, y):
    return x + y

print("----------------")
func(1, 2)



''' inner3 = wrapper3(func) inner2 = wrapper2(inner3) inner1 = wrapper1(inner2) func = inner1 '''

複製代碼

裝飾器使用場景

# -*- coding:utf-8 -*-


''' 一、參數、結果檢查 二、緩存 三、計數 四、日誌 五、統計 六、權限管理 七、重試 '''

#=====================================================================
''' 一、參數檢查是否合格 需求:計算年齡平均值,年齡不能爲負數 '''
# def warpper(f):
# def inner(*args,**kwargs):
# for i in args:
# if i <= 0:
# print("輸入年齡有誤")
# return
# res = f(*args,**kwargs)
# return res
# return inner
#
# @warpper
# def avgYears(*args):
# sum = 0
# for i in args:
# sum += i
# av = sum/len(args)
# return av
#
# print(avgYears(10,12,-2))

''' 結果檢查 題目:計算兩個數的和,結果超過100則給出警告,不然輸出兩個數的和 '''
# def wrapper(f):
# def inner(a,b):
# res = f(a,b)
# if res > 100:
# print("警告")
# else:
# return res
# return inner
# @wrapper
# def sum(a,b):
# return a+b
# print(sum(100,2))

''' 計數 題目:對函數調用次數統計 '''
# def wrapper(f):
# count = 0
# def inner(*args,**kwargs):
# res = f(*args,**kwargs)
# nonlocal count
# count += 1
# print("函數第%d次調用"%(count))
# return res
# return inner
#
# @wrapper
# def sum(a,b):
# return a+b
#
# @wrapper
# def f():
# print("fanding is a good man")
#
# print(sum(1,2))
# print(sum(4,5))
# f()
# f()

''' 重試 題目:數據庫鏈接重試 '''
# import time
# def retry(count=3,wait=0,exceptions=(Exception,)):
# def deco(f):
# def inner(*args,**kwargs):
# for i in range(count):
# try:
# res = f(*args,**kwargs)
# except:
# time.sleep(wait)
# continue
# else:
# return res
# return inner
# return deco
#
# import random
# @retry(3)
# def conn(ip, port, dbName, passwd):
# num = random.choice([1, 2, 3, 4])
# print("**************", num)
# if num <= 2:
# 10 / 0
#
# conn("","","","")
複製代碼

可迭代對象

# -*- coding:utf-8 -*-

''' 概念:能夠直接做用於for循環的對象統稱可迭代對象(Iterable) 能夠直接做用於for循環的數據類型: 一、集合數據類型,如list、tuple、dict、set、string等 二、generator,包含生成器和帶yield的generator function 注意:能夠使用isinstance()函數判斷一個對象是不是Iterable對象 '''

from collections import Iterable

print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance("sunck", Iterable))
print(isinstance((x for x in range(10)), Iterable))
print(isinstance(100, Iterable))

複製代碼

列表生成式

# -*- coding:utf-8 -*-

''' 做用:python內置的很是簡單而且強大的能夠用來生成list的生成式 '''

# 生成列表
# 缺點:只能生成簡單的列表
print(list(range(1, 11)))


# 需求:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 循環生成列表
# 缺點:循環比較繁瑣
li = []
for i in range(1, 11):
    li.append(i * i)
print(li)

# 列表生成式生成列表
li2 = [x * x for x in range(1, 11)]
print(li2)


# 列表生成式的for循環後能夠加判斷
li3 = [x * x for x in range(1, 11) if x % 2 == 0]
print(li3)


# 排列 組合 排列組合
# 使用雙層循環,生成全排列
li4 = [m + n for m in "ABC" for n in "123"]
print(li4)





#六位密碼全排列
# import string
# cc = 0
# print(type(string.digits))
# password = (a+b+c+d+e+f for a in string.digits for b in string.digits for c in string.digits for d in string.digits for e in string.digits for f in string.digits)

複製代碼

生成器

# -*- coding:utf-8 -*-

''' 概念: 經過列表生成式,能夠直接建立一個列表。全部的數據都會存到內存中,受內存的限制,列表的容量是有限制的。若是列表中有10000個數據,若是咱們只需訪問前幾個元素,後面的基本不會訪問,那麼形成內存極大的浪費。 若是列表中的元素能夠按照某種算法推導出來,那麼咱們在循環遍歷列表時不斷推導後面的元素,從而節省大量內存。在python中,這種一邊循環一邊推導的機制稱爲生成器(generator) '''


#建立生成器
# 一、修改列表生成式:將列表生成式的[]改成()便可
g = (x  for x in range(1, 6))
print(g)
print(type(g))
#生成器特色:能夠經過next()函數得到generator的下一個值
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# # 當全部元素都拿出來後在執行next會獲得StopIteration異常
# print(next(g))

#遍歷
#原理:generator保存的是算法,每次調用next()就計算生成器下一個元素的值,直到拋出StopIteration錯誤爲止
# while 1:
# print(next(g))
# print("sunck is a goo dman")
# 之後通常都是使用for循環來迭代生成器,不須要關心StopIteration異常
for i in g:
    print(i)

複製代碼

函數實現生成器

# -*- coding:utf-8 -*-

''' 推導的算法比較複雜,用列表生成式for循環沒法實現的時候能夠選擇使用函數生成生成器 '''

# 函數是按順序執行,遇到return語句或者最後一行函數語句就返回。
# 若是想讓一個函數變爲生成器函數,只需將函數的return改成yield
# 變成generator函數,在每次調用next()的時候,遇到yield語句返回,若是再次執行next(),會從上次返回的yield語句處繼續執行
def func():
    yield 0
    print("sunck is a good man")
    yield 1
    print("sunck is a nice man")
    yield 2
    print("sunck is a cool man")
    yield 3

res = func()
# print(res)
# print(type(res))
print(next(res))
print(next(res))
print(next(res))
print(next(res))
# 遇到yield中斷,再繼續執行沒有yield會報錯
# print(next(res))

複製代碼

斐波那契數列練習

# -*- coding:utf-8 -*-

''' 0, 1,1,2,3,5,8,13, '''

#編寫函數實現斐波那契數列
# def fib(count):
# index = 0
# x, y = 0, 1
# while index < count:
# print(y)
# x, y = y, x + y
# index += 1
# fib(5)



# 生成器實現
# def fib(count):
# index = 0
# x, y = 0, 1
# while index < count:
# yield y
# x, y = y, x + y
# index += 1
#
# g = fib(6)
# for i in g:
# print(i)





def fib(count):
    index = 0
    x, y = 0, 1
    while index < count:
        yield y
        x, y = y, x + y
        index += 1
    return "sunck is a good man"

g = fib(6)
# for循環遍歷generator時,拿不到generator的return與的返回值
# 若是想拿返回值,必須捕獲StopIteration錯誤,返回值包含在錯誤對象的value屬性中
while 1:
    try:
        ret = next(g)
        print(ret)
    except StopIteration as e:
        print("返回值:", e.value)
        break

複製代碼

迭代器

# -*- coding:utf-8 -*-

''' 概述: 一、能夠被next()函數調用並返回一個值的對象稱爲迭代器對象(Iterator) 二、迭代器不但能夠做用於for循環,還能夠被next()調用 '''

from collections import Iterator
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance("sunck", Iterator))
print(isinstance((x for x in range(1, 5)), Iterator))


#轉成Iterator對象
li = [1,2,3,4,5]
# 將可迭代對象轉爲迭代器
li = iter(li)
print(next(li))
print(next(li))
print(next(li))
print(next(li))
print(next(li))



# 爲何list、dict、str、set等數據類型不是Iterator
# Iterator對象表示的是一個數據流,Iterator對象能被一個next()函數調用並返回一個數據 ,直到拋出StopIteration錯誤。能夠把數據流當作是一個有序的序列,可是不肯定這個序列的長度,只能經過next()函數不斷計算下一個數據,因此說Iterator的設計是惰性求值的。Iterator能夠表示一個無限大的數據流,而list永遠不可能存儲無限的數據

複製代碼

import語句

格式:import module1[, module2[, module3[, module4], ……]]
注意:一個模塊只會被導入一次,無論你執行了多少次import,有效的防止導入模塊被一次次的執行

使用模塊中的內容:
    module.方法/變量/類
複製代碼

from...import語句

做用:從模塊中導入一個指定的部分
格式:from modulename import name1[, name2[, name3], ……]
複製代碼

from...import*語句

做用:把一個模塊的全部內容所有導入當前命名空間
格式:from modulename import *
注意:不該該過多的使用,極可能形成變量的衝突
複製代碼

__name__屬性

每一個模塊都一個__name__屬性,當其值爲"__main__"時,代表該模塊自身在運行,不然是被當作模塊引入,此時值爲模塊的名字

做用:模塊就是一個可執行的python文件,一個模塊被另外一個模塊引入,向讓模塊中的某一程序不執行,咱們能夠用__name__屬性來使程序隱藏該塊代碼,當自身執行時在執行該塊代碼
複製代碼

模塊概述

在計算機程序的開發過程當中,隨着程序代碼越寫越多,在一個文件裏代碼就會愈來愈長,愈來愈難以維護
爲了編寫可維護性的代碼,咱們會把不少函數進行分組,分別放到不一樣的文件裏,這樣,每一個文件包含的代碼就相對較少,大多數編程語言都是採用這種組織代碼的方式。在python中,一個.py文件就稱之爲一個模塊(module)



優勢:
    一、提升了代碼的可維護性
    二、提升了代碼的複用度,編寫代碼沒必要從零開始,當一個模塊編寫完成,就能夠被其餘地方引用
    三、引用其餘模塊,包含python內置模塊和第三方模塊
    四、避免函數名和變量名等命名的衝突

複製代碼

time模塊

名詞

UTC(世界協調時間):格林尼治時間,世界標準時間。在中國UTC+8
DST(夏令時):是一種爲了節約能源而認爲規定地方時間的制度,通常在天亮早的夏季將時間提早一小時

複製代碼

時間表示形式

一、時間戳
    以整型或者浮點型表示的是一個以秒爲單位的時間間隔,這個時間的基礎值是1970年1月1日零時開始算
二、元組形式
    一種python的數據結構表示,這個元組有9個整型元素,分別表示不一樣的時間含義
   year
   month(1-12)
   day(1-31)
   hours(0-23)
   minutes(0-59)
   seconds(0-59) 
   weekday(0-6,星期一爲0)
   Julian day(1-366):表示當前日期在本年是第幾天,day in the year
   DST flag(-1 or 0 or 1):夏令時格式,0表示正常格式,1表示爲夏令時格式,-1表示根據當前的日期時間格式來斷定
三、格式化字符串
    %a    本地簡化星期名稱
    %A    本地完整星期名稱
    %b    本地簡化月份名稱
    %B    本地完整月份名稱
    %c    本地相應的日期和時間表示
    %d    一個與中的第幾天(01-31)
    %H    一天中的第幾個小時(24時制,00-23)
    %I    一天中的第幾個小時(12時制,01-12)    
    %j    一年中的第幾天(001-366)
    %m    月份(01-12)
    %M    分鐘數(00-59)
    %p    本地am或者pm的相應符號
    %S    秒(00-59)
    %U    一年中的星期數,以星期天爲一個星期
    %w    一個星期中的第幾天(0-6, 0表示星期日)
    %W    和%U基本相同,以星期一爲一個星期
    %x    本地相應日期
    %X    本地相應時間
    %y    去掉世紀的年份(00-99)
    %Y    完整的年份
    %Z    時區的名字,若是不存在爲空字符串

複製代碼

方法

# time()
#返回當前的時間戳,浮點數形式,無需傳參
t1 = time.time()
print(t1)

複製代碼
# gmtime()
# 將時間戳轉換爲UTC時間元組格式,接收一個浮點型時間戳爲參數,若是不傳默認值爲當前時間的時間戳
t2 = time.gmtime()
print(t2)

複製代碼
# localtime()
# 將時間戳轉換爲本地時間元組格式,接收一個浮點型時間戳爲參數,若是不傳默認值爲當前時間的時間戳
t3 = time.localtime()
print(t3)

複製代碼
# mktime()
# 將本地時間元組轉爲時間戳,接受一個時間元組
t4 = time.mktime(t3)
print(t4)

複製代碼
# asctime()
# 將時間元組格式轉爲字符串形式,接受一個時間元組,默認值爲localtime時間的時間元組
t5 = time.asctime(t3)
print(t5)
print(type(t5))

複製代碼
# ctime()
# 將時間戳轉爲字符串,接受一個時間戳,默認值爲當前時間戳
t6 = time.ctime()
print(t6)
print(time.asctime(time.localtime()))

複製代碼
# strftime()
# 將時間元組以指定的格式轉換爲字符串形式,接受一個字符串格式化串、時間元組(默認爲localtime())
t7 = time.strftime("%Y-%m-%d %X", t3)
print(t7)

複製代碼
# strptime()
# 將指定格式的時間字符串解析爲時間元組,是strftime逆過程,
t8 = time.strptime("1999-10-01 08:08:08", "%Y-%m-%d %X")
print(t8)

複製代碼
# sleep()
# 延遲一個時間段,接收整型或者浮點型

複製代碼
# clock()
# 返回當前程序執行時間,Unix系統始終返回所有運行時間,而windows從第二次開始都是以第一次調用此函數的時間戳爲基準,而不是以程序開始時間爲基準

複製代碼

datetime模塊

概述

datetime 比 time 高級了很多,能夠理解爲 datetime 基於time進行了封裝,提供了更使用的函數接口,datetime模塊的接口更直觀、更容易調用

複製代碼

模塊中的類

模塊中的類:
    time      只關注時間
    date      只關注日期
    datetime  同時有時間和日期   
    timedelta 主要用於計算時間跨度
    tzinfo    時區相關

複製代碼

方法

# 獲取當前時間
t1 = datetime.datetime.now()
print(t1)
print(type(t1))

複製代碼
# 獲取指定時間
t2 = datetime.datetime(1999, 10, 1, 8, 8, 8, 0)
print(t2)

複製代碼
# 將時間轉爲字符串
t3 = t1.strftime("%Y-%m-%d %X")
print(t3)
print(type(t3))

複製代碼
#將格式化字符串轉爲datetime對象
t4 = datetime.datetime.strptime(t3, "%Y-%m-%d %X")
print(t4)
print(type(t4))

複製代碼
# 時間相減,返回一個時間間隔
t5 = datetime.datetime(1999, 10, 1, 8, 8, 8, 0)
t6 = datetime.datetime(1999, 10, 2, 9, 8, 8, 0)
t7 = t6 - t5
print(t7)
print(type(t7))
#間隔天數
print(t7.days)
#除去間隔天數之外的間隔秒數
print(t7.seconds)

複製代碼

calendar模塊

import calendar

複製代碼
#返回指定年的某月
# print(calendar.month(2018, 8))

複製代碼
# 返回指定年的日曆
# print(calendar.calendar(2018))

複製代碼
# 判斷某一年是不是閏年
# print(calendar.isleap(2000))

複製代碼
#返回某個月的weekday的第一天和這個月的全部天數
# print(calendar.monthrange(2017, 8))

複製代碼
#返回某個月以一週爲週期的元素序列
print(calendar.monthcalendar(2018, 12))

複製代碼

collections模塊

namedtuple

概述:
# namedtuple
# 命名元組,本質是一個函數,用它來建立一個自定義的tuple對象
# 規定tuple元素的個數,並能夠用屬性而不是索來引用tuple中的元素
# 用namedtuple定義一個新的數據類型


複製代碼
# 假如這是一個點的座標,可是沒有寫註釋,過了很久就不知道了
p = (1, 2)
#定義了一個新的數據類型,屬於tuple類型的子類型
Point = namedtuple("Point", ["x", "y"])
point = Point(1, 2)
print(isinstance(point, tuple))
print(isinstance(point, Point))
print(point)
print(point[0], point[1])
# 根據屬性獲取值
print(point.x, point.y)


複製代碼

deque

# deque
# 使用list存儲數據,按索引訪問元素,可是插入和刪除元素會根據元素的個數增多而效率下降。由於list是線性存儲,數據量大插入和刪除效率會低
# deque 就是爲了高效實現插入和刪除操做的雙向列表,適用於隊列和棧


複製代碼
q = deque([1,2,3,4,5])

q.append(6)
q.appendleft(0)
q.pop()
q.popleft()
print(q)


複製代碼

defaultdict

from collections import defaultdict

# 使用dict時,若是引用的key不存在,會拋出KeyError異常。若是但願key不存在時,能獲得一個默認的值,就使用defaultdict

d1 = {"a":1, "b":2, "c":3}
# print(d1["d"])
print(d1.get("d"))


d2 = defaultdict(lambda :"good")
d2["a"] = 1
print(d2)
print(d2["a"])
print(d2["d"])
print(d2.get("d"))


複製代碼

OrderedDict

from collections import OrderedDict

#使用dict時,key是無序的。對dict作迭代時沒法保證key的順序。若是須要key有順序,就能夠使用OrderdDict
d1 = {"a":1, "b":2, "c":3}
print(d1)

# 順序是按照鍵值對插入的順序
d2 = OrderedDict([("a",[11, 111]),("c",33),("b",22)])
print(d2)
print(d2["a"])
print(d2.get("a"))


複製代碼

Counter

from collections import Counter

# 一個簡單的計數器,本質上是dict的一個子類

# 計算集合中每一個元素出現的次數
a = "sunck is a good man"
c = Counter()
print(c)
for ch in a:
    c[ch] = c[ch] + 1
print(c)
結果:
Counter({' ': 4, 's': 2, 'n': 2, 'a': 2, 'o': 2, 'u': 1, 'c': 1, 'k': 1, 'i': 1, 'g': 1, 'd': 1, 'm': 1})


複製代碼

uuid模塊

概述

概述:
    是128位的全局惟一標識符,一般由32字節的字母串表示,它能夠保證時間和空間的惟一性,也稱爲GUID


複製代碼

原理

原理:
    經過MAC地址、時間戳、命名空間、隨機數、僞隨機數來保證生產的ID的惟一性


複製代碼

做用

做用:
    隨機生成字符串,當成token使用,當成用戶帳號使用,當成訂單號使用等(要求不相同字符串)


複製代碼

算法

算法:
    一、uuid1()基於時間戳
        有MAC地址,當前時間錯,隨機數字,能夠保證全球範圍內的惟一性。可是因爲MAC地址的使用時帶來安全問題,局域網中能夠使用IP來代替MAC
    二、uuid2()基於分佈式計算環境DCE
        算法和uuid1相同,不一樣的是把時間戳的前四位換位POSIX的UID,實際當中不多使用,注意,Python中沒有這個函數
    三、uuid3()基於名字和MD5散列值
        經過計算名字和命名空間的MD5散列值獲得的,保證了同一命名空間中不一樣名字的惟一性,和不一樣命名空間的惟一性,但同一命名空間的相同名字生成相同的uuid
    四、uuid4()基於隨機數
        有僞隨機數獲得的,有必定重複機率的,這個機率而且是能夠計算出來的
    五、uuid5()基於名字和SAH1散列值
        算法和uuid3()相同,不一樣的是使用SHA1算法
        


複製代碼

使用經驗

使用經驗:
    一、python中沒有基於DCE的,因此uuid2()能夠忽略
    二、uuid4()存在機率性重複,因爲無映射性,最好不用
    三、若是在全局的分佈式環境下,最好使用uuid1()
    四、若名字的惟一性要求,最好使用uuid3()或uuid5()


複製代碼

用法

print(uuid.uuid1())
print(uuid.uuid4())
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "kaige"))
print(uuid.uuid5(uuid.NAMESPACE_DNS, "sunck"))


複製代碼

base64模塊

概述

概述:用記事本打開圖片等文件,看到一坨亂碼,由於二進制文件包含不少沒法顯示的內容。因此想讓記事本能處理二進制數據,就須要將二進制字符串轉換。base64是一種比較常見的二進制編碼方法


複製代碼

編碼原理

編碼原理:
    一個包含64個字符的數組
    ['A', 'B', ……, 'a', 'b', ……, '0', '1', ……, '+', '/']
    
    對二進制數據進行處理,每一個三個字節一組,一組就是3x8=24bit,劃爲4組,每組正好6bit

    獲得4個數字做爲索引,而後查表,得到相應的4個字符,就是編碼後的字符串
    


複製代碼

做用

做用:
    適用於小段內容的編碼,好比數字證書籤名,cookie,網頁中傳輸的少許二進制數據
    


複製代碼

注意

注意:base64是一種經過查表的編碼方法,不能用於加密,即便修改了字符對照表頁不行。


複製代碼

使用

#編碼
s1 = b"sunck is a good ma"
print(base64.b64encode(s1))
#解碼
s2 = b"c3VuY2sgaXMgYSBnb29kIG1h"
print(base64.b64decode(s2))


複製代碼

特例

#若是要編碼的二進制不是3的倍數,怎麼辦?
#答:base用\x00字節在末尾補足,在編碼的末尾加上1個或2個等號表示補了多少個字節,解碼時會自動去掉
s3 = b"sunck is a good man"
print(base64.b64encode(s3))


複製代碼
# 因爲標準base64編碼後可能出現字符+和/,在URL中就不能直接做爲參數
# 提供urlsafe_b64encode編碼,保證url的安全,將+和/替換成-和_,提供urlsafe_b64decode進行url安全解碼
s4 = b"sunck is a good m~"
print(base64.b64encode(s4))
print(base64.urlsafe_b64encode(s4))

s5 = b"c3VuY2sgaXMgYSBnb29kIG1-"
print(base64.urlsafe_b64decode(s5))


複製代碼
#因爲=字符也可能出如今base64編碼中,可是=在url、cookie裏面會形成歧義,因此不少base64編碼後會把=去掉
s6 = b"abcd"
s8 = base64.b64encode(s6)
print(s8)
# b"abcd" --> b'YWJjZA=='
# b"abcd" --> b'YWJjZA'
s7 = b'YWJjZA=='
print(base64.b64decode(s7))


複製代碼
#能夠自定義編碼對照表列表中64個字符的排序,這樣能夠自定義編碼,可是一般狀況下沒有任何須要


複製代碼

hashlib模塊

概述

hashlib 模塊提供了常見的摘要算法,如MD5,SHA1

摘要算法(又稱哈希算法、散列算法):
    原理:它經過一個函數,把任意長度的數據轉爲一個長度固定的數據串(一般用16進制的字符串表示)


複製代碼

MD5

# 最多見的摘要算法,速度快,一般用32位16進制字符串表示
s1 = b"sunck is a good man"
m5 = hashlib.md5()
m5.update(s1)
print(m5.hexdigest())

#若是數據量比較大, 能夠分屢次調用update,最後的結果是同樣的
m6 = hashlib.md5()
m6.update(b'sunck is ')
m6.update(b"a good man")
print(m6.hexdigest())


複製代碼

SHA1

#SHA1
# 調用SHA1與調用MD5徹底同樣,一般用40位16進制字符串表示
s2 = b"sunck is a nice man"
sh1 = hashlib.sha1()
sh1.update(s2)
print(sh1.hexdigest())


複製代碼

更安全的

#更安全的
# SHA256
# SHA512
# 越安全的算法不只越慢,並且摘要會越長



#有沒有兩個不一樣的數據經過hash算法後獲得了相同的摘要呢?
#有這種可能性,由於摘要算法是將無限多的數據映射到有限的集合中,若是兩個數據的摘要相同,稱之爲碰撞。可能出現,可是很是渺茫


複製代碼

總結

應用:
    任何容許用戶登錄的網站都會存儲用戶登陸的用戶名和密碼,那麼密碼通常存儲的是原密碼的摘要值。
    
    sunck--good明文存到數據中,若是數據庫泄露,全部用戶信息會暴露
    
    正確的保存口令方式不是存儲明文內容,而是存儲口令的摘要,當用戶登陸時,首先會計算用戶輸入的明文口令的摘要,和數據庫中的對比,若是一直說明口令正確,不然必定錯誤。


複製代碼

hmac模塊

import  hmac

''' 實現HMAC算法,是用一個key對數據進行「雜湊」後在記性的hash,使用hmac比hash算法更安全,不一樣的key會產生不一樣的hash '''
#對於同一條數據,key不一樣會獲得不一樣的摘要值
s = b"sunck is a good man"
key = b"secret"
h = hmac.new(key, s, digestmod="MD5")
print(h.hexdigest())


複製代碼

itertools模塊

無限迭代

import itertools
import time
# 無限迭代
# count(start=0, step=1)
# c = itertools.count()
# for i in c:
# print(i)
# time.sleep(1)



# cycle(iterable)
# 把傳入的一個序列無限重複下去
# cy = itertools.cycle("sunck")
# for i in cy:
# print(i)
# time.sleep(1)

# repeat(object[, times])
# 把一個元素無限重複下去,若是提供了第二個參數,就能夠指定重複次數
# r = itertools.repeat("sunck", 3)
# for i in r:
# print(i)
# time.sleep(1)


複製代碼

有限迭代

# 有限迭代
# 把一組迭代對象串聯起來,造成一個更大的迭代器
# chain(*iterables)
# cha = itertools.chain("ABC", "abc")
# for i in cha:
# print(i)
# time.sleep(1)
# 把迭代器中相鄰的重複元素跳出來放在一塊兒
# g = itertools.groupby("AABBBBccdedFFF")
# for key, value in g:
# print(key, list(value))
# time.sleep(1)


複製代碼

排列組合

#全排列
# 從n個不一樣元素中取出m(m<=n)個元素,按照必定的順序排成一列,叫作從n個元素中獲取m個元素的一個排列。當m==n時,這個排列稱爲全排列
# itertools.permutations(iterable, length)
# p = list(itertools.permutations([1,2,3,4], 4))
# print(p)
# print(len(p))
''' 5! = 1 * 2 * 3 * 4 * 5 0! = 1 1! = 1 從n箇中選m個 n! / (n - m)! 4 1 4!/3! 4 2 4!/2! 4 3 4!/1! 4 4 4!/0! '''


#組合
# 從n個不一樣的元素中,任意m(m<=n)個元素爲一組,叫作從n個不一樣元素中取出m個元素的組合
# itertools.combinations(iterable, length)
# c = list(itertools.combinations([1,2,3,4], 3))
# print(c)
# print(len(c))

''' 4 4 1 4 3 4 4 2 6 4 1 4 n!/m!(n-m)! '''

#排列組合(笛卡爾積)
# itertools.product(*iterable, repeat=1)
# passwds = list(["".join(x) for x in itertools.product("0123456789", repeat=6)])
# print(passwds)
# print(len(passwds))



# passwds = ("".join(x) for x in itertools.product("0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm", repeat=8))
# for i in passwds:
# print(i)
# time.sleep(1)
# 暴力破解
# 枚舉破解


複製代碼

安裝三方模塊

''' Windows pip install 模塊名 pip install 模塊名==版本號 Linux(超級root用戶) 超級用戶根本就不可能給你用 pip install 模塊名 pip install 模塊名==版本號 Linux(普通用戶) sudo pip install 模塊名 sudo pip install 模塊名==版本號 '''


複製代碼

Pillow模塊

from PIL import Image

# pip install Pillow
# 處理圖形圖像

im = Image.open("1.jpg")
# 打印圖片的信息
# print(im.format, im.size, im.mode)
# 設置圖片大小
im.thumbnail((100, 80))
#生成新圖片
im.save("2.jpg", "JPEG")


複製代碼

面向對象

什麼是面向對象

自上而下順序執行,逐步求精;其程序結構是按功能劃分爲若干個基本模塊,這些模塊造成一個樹狀結構;各模塊之間的關係儘量簡單,在功能上相對獨立;每一模塊內部均是由順序、選擇和循環三種基本結構組成;其模塊化實現的具體方法是使用子程序。程序流程在寫程序時就已決定。


把數據及對數據的操做方法放在一塊兒,做爲一個相互依存的總體——對象。
對同類對象抽象出其共性,造成類。
類中的大多數數據,只能用本類的方法進行處理。
類經過一個簡單的外部接口與外界發生關係,對象與對象之間經過消息進行通訊。
程序流程由用戶在使用中決定。



複製代碼

理解面向對象

面向對象是相對面向過程而言
面向對象和麪向過程都是一種思想
面向過程
強調的是功能行爲
關注的是解決問題須要哪些步驟 
面向對象
將功能封裝進對象,強調具有了功能的對象
關注的是解決問題須要哪些對象 
面向對象是基於面向過程的。

複製代碼

面向對象特色

是一種符合人們思考習慣的思想
能夠將複雜的事情簡單化
將程序員從執行者轉換成了指揮者

完成需求時:
先要去找具備所需的功能的對象來用。
若是該對象不存在,那麼建立一個具備所需功能的對象。

複製代碼

類的定義

生活中描述事物無非就是描述事物的名稱/屬性和行爲。如:人有身高,體重等屬性,有說話,打架等行爲。Python中用類來描述事物也是如此屬性:對應類中的成員變量。行爲:對應類中的成員方法。定義類其實在定義類中的成員(成員變量和成員方法) 擁有相同(或者相似)屬性和行爲的對象均可以抽像出一個類

複製代碼

類的設計

只關心3樣東西	事物名稱(類名):人(Person)	屬性:身高(height)、年齡(age)	行爲(功能):跑(run)、打架(fight)

複製代碼

訪問對象方法

# -*- coding:utf-8 -*-

''' 對象方法 經過實例調用時(沒法用類名調用),能夠引用類內部的任何屬性和方法 格式:對象名.方法名(參數列表) 注意:對象方法的第一個參數必須是self,其他參數按順序排列,調用傳參是忽略self self:表明一個對象,哪一個對象調用的對象方法,那麼在方法中self就表明哪一個對象 類方法 無需實例化,用類名調用(能夠用對象調用),能夠調用類的屬性和方法,沒法取到普通的對象屬性和方法,使用@classmethod定義類方法 cls:表示類名 靜態方法: 不管用類調用仍是用實例調用,都沒法獲取到類內部的屬性和方法,徹底獨立的一個方法,使用@staticmethod定義 總結: 類方法效率要比對象方法高,由於類方法無需實例化對象,而且節省內存,當方法中不涉及對象屬性和方法時使用 靜態方法通常用做工具方法 '''

class Person(object):
    # 對象方法
    def eat(self, x, y):
        print(self)
        print(self.eat2("a", "b"))
        return "吃%s和%s"%(x, y)
    def eat2(self, x, y):
        return "2吃%s和%s"%(x, y)
    #類方法
    @classmethod
    def run(cls, m):
        print(cls.run2(80))
        return ("跑%d米"%m)
    @classmethod
    def run2(cls, m):
        return ("2跑%d米" % m)
    #靜態方法
    @staticmethod
    def play(x):
        return "玩%s"%x
per1 = Person()
per = Person()
print(per, per1)

#調用對象方法
print(per1.eat("蘋果", "香蕉"))
#調用類方法
# print(Person.run(200))
#調用靜態方法
# print(per.play("球"))
# print(Person.play("麻將"))





class Gongju():
    @staticmethod
    def a():
        pass
    @staticmethod
    def b():
        pass

Gongju.a()
Gongju.b()

複製代碼

類屬性

# -*- coding:utf-8 -*-

class Person(object):
    #類屬性:能夠經過類調用,也能夠經過對象調用
    # 當類的對象的屬性值都同樣時就使用類屬性
    name = "lilei"
    age  = 20
    height = 170
    weight = 80

#在初始化對象時,每個對象的屬性值多相同了
per1 = Person()
per2 = Person()
#經過對象訪問屬性 對象名.屬性名
print(per1.name)
print(per2.name)

#每一個對象擁有本身的屬性
per1.name = "hanmeimei"
print(per1.name)
print(per2.name)

print("-------------------")
print(Person.name)


#問題:使用類建立的全部的對象的屬性初始值都同樣

複製代碼

對象的初始狀態

# -*- coding:utf-8 -*-

# 需求:在建立對象時給每一個對象直接賦值屬性的初始值

# __init__()
# 構造方法,在使用類建立實例對象時自動調用,目的是初始化對象內容。

class Person(object):
    # 後期除非定義單例類,不然基本不用寫
    def __new__(cls, *args, **kwargs):
        # 調用父類中的__new__方法開闢內存空間
        return super(Person, cls).__new__(cls)

    #類屬性
    def __init__(self, name, age, height, weight):
        # 對象屬性,只能對象調用
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        # 對象方法中能夠調用對象屬性
        return "my name is %s, I am %d years old"%(self.name, self.age)

#建立對象時給每一個對象的屬性賦值
per1 = Person("lilei", 20, 170, 80)
per2 = Person("hanmeimei", 18, 165, 50)

print(per1.name)
print(per2.name)

# print(Person.name) #類中沒有name屬性,且類名沒法調用對象屬性


print(per1.say())
print(per2.say())



# 延伸
# __new__()方法:是一個類方法,返回一個對象的實例,在使用類實例化對象時自動調用,目的是在堆區開闢一片內存空間,會在__init__以前調用
# 使用:建立單例類

複製代碼

析構函數

# -*- coding:utf-8 -*-

class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

    # 析構方法,在釋放對象時自動調用
    # 做用:釋放一些沒必要要的內存
    def __del__(self):
        print("object delete")

    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80)
del per

複製代碼

訪問限制

# -*- coding:utf-8 -*-

class Person(object):
    # 在python中,變量名相似__xxxx__的,屬於特殊變量,特殊變量時能夠直接訪問的,不是私有變量
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
        # 在python中_xxx變量,這樣的實例變量我不是能夠直接訪問的。可是,按照約定俗成的規定,當看到這樣的變量時,意思是雖然我能夠被外部直接訪問,可是請把我視爲私有變量,不要在外部隨意訪問
        self._temp = 2
        # 特殊變量
        self.__test__ = 1
        #若是要讓內部屬性不被外部訪問,能夠把屬性的名稱前加上兩個下劃線
        #python中,示例的變量以__開頭,就變成了一個私有屬性(private),只能在內部訪問,外部沒法訪問
        #不能再外部直接訪問__money的緣由是python解釋器對外把__money屬性改爲了_Person__money。因此任然能夠用_Person__money來直接訪問,可是強烈建議不要這麼作,由於不一樣版本的python解釋器可能會把__money改爲不一樣的屬性名
        self.__money = money



    #定義公有方法間接訪問私有屬性
    def getMoney(self):
        return self.__money
    def setMoney(self, money):
        if money >= 0:
            self.__money = money

    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80, 100)
per.age = 18
print(per.age)

# print(per.__money)
#間接訪問私有屬性
per.setMoney(10)
print(per.getMoney())
# print(per._Person__money) #不建議使用
print(per.__test__)
print(per._temp)

複製代碼

@property

# -*- coding:utf-8 -*-

class Person(object):
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
        self.__money = money
    @property
    def money(self):
        return self.__money
    @money.setter
    def money(self, value):
        if value < 0:
            self.__money = 0
        else:
            self.__money = value
    #定義公有方法間接訪問私有屬性
    # def getMoney(self):
    # return self.__money
    # def setMoney(self, money):
    # if money < 0:
    # self.__money = 0
    # else:
    # self.__money = money
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80, 100)

# print(per.getMoney())
# per.setMoney(10)
# print(per.getMoney())

per.age = 15
print(per.age)

print("-------------")
#向讓訪問私有屬性的方式相似訪問普通屬性,須要使用@property
#讓私有屬性能夠使用點語法
print(per.money)  #至關於執行money()方法
per.money = -10
print(per.money)

複製代碼

動態給實例添加屬性和方法、__slots__槽

# -*- coding:utf-8 -*-
class Person(object):
    __slots__ = ("name", "age", "height", "weight", "money", "run")
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per1 = Person("lilei", 20, 170, 80)
per2 = Person("hanmeimei", 18, 165, 50)
print(per1.say())

#實例化一個對象後,能夠給對象綁定任何的屬性和方法,這就是動態語言的靈活性
#若是屬性不存在,則變爲增長屬性
per1.money = 100
print(per1.money)
#增長方法
def run(self):
    print("run")
from types import MethodType
per1.run = MethodType(run, per1)
per1.run()
#注意:給一個實例對象綁定的屬性和方法對另外一個實例對象沒有影響
# print(per2.money)


#需求:給全部的實例都綁定屬性和方法
#解決:給類綁定就能夠了
#注意:不只僅給已存在的對象會綁定,未建立的對象也綁定了
Person.faceValue = 100
def play(self):
    print("play")
Person.play = play
print(per1.faceValue, per2.faceValue)
per1.play()
per2.play()
per3 = Person("laowang", 50, 167, 60)
print(per3.faceValue)



#思考:想限制實例的屬性,不讓對象隨意添加屬性,只能添加咱們規定一些屬性
#解決:在定義類時,頂一個特殊屬性__slots__,限制該類實例能添加的屬性
# per1.score = 100

複製代碼

單例

概述

# -*- coding:utf-8 -*-

''' 單例:是一種軟件設計模式,該模式的主要目的是確保一個類只有一個實例存在 實現單例的方式: 一、使用模塊 二、使用__new__ 三、使用裝飾器 四、使用元類 '''

複製代碼

使用--new--()實現單例

# -*- coding:utf-8 -*-

class Card(object):
    def __new__(cls, *args, **kwargs):
        # 每一次實例化的時候,我麼都只返回instance同一個對象
        if not hasattr(cls, "instance"):
            cls.instance = super(Card, cls).__new__(cls)
        return cls.instance


card1 = Card()
card1.passwd = "666666"
card2 = Card()
print(card2.passwd)
print(card1 is card2)

複製代碼

使用裝飾器實現單例

# -*- coding:utf-8 -*-

def singleton(cls):
    instances = {}
    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance


@singleton
class Card(object):
    pass
@singleton
class Person(object):
    pass


c1 = Card()
c2 = Card()
print(c1 is c2)

p1 = Person()
p2 = Person()
print(p1 is p2)

複製代碼

重寫--repr--和--str--方法

# -*- coding:utf-8 -*-


class Person(object):
    #重寫:將繼承的方法重寫寫一遍,在原有的功能基礎上添加一些新的功能
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)
    #需求:打印該類型的對象時,想打印出對象的各個屬性值
    #解決:重寫__str__方法
    #__str__()方法:在調用print打印對象時自動調用

    #是顯示給用戶的
    def __str__(self):
        return "name:%s\nage:%d\nheight:%.2f\nweight:%.2f"%(self.name, self.age, self.height, self.weight)
    #是給機器用的,在python解釋器裏直接敲對象後回車自動調用
    def __repr__(self):
        return "name:%s\nage:%d\nheight:%.2f\nweight:%.2f"%(self.name, self.age, self.height, self.weight)

per = Person("lilei", 20, 170, 80)
print(per)

複製代碼

異常處理、調試、測試

錯誤處理

# -*- coding:utf-8 -*-



'''概述 在程序運行過程當中,總會遇到各類各樣的錯誤,有的錯誤時編程代碼有問題形成的,這種錯誤一般稱爲BUG,BUG是必須修復的。有的錯誤是用戶輸入形成的,這種錯誤的能夠經過檢查用戶的輸入來作響應處理。還有一種錯誤時徹底沒法在程序運行過程當中預測的,好比寫文件的時候,磁盤滿了,寫不進去了,再好比從網絡中抓取數據,忽然斷網了,一般這種狀況稱爲異常,在程序中必需要處理的,不然程序會因各類問題而退出 '''



# 遇到錯誤,最原始的方式解決方法是事先約定一個錯誤代碼,這樣就知道是否有錯,在操做系統提供的調用中很是經常使用
''' 缺陷: 一、函數自己返回的數據與錯誤碼會混在一塊兒,須要大量的判斷是否出錯 二、一旦出錯,要一級一級上報,直到某個函數能夠處理 '''

#錯誤代碼
# print(10 / 0)


#需求:當程序遇到錯誤時,不讓程序結束,而是越過錯誤繼續向下執行
'''try……except……else語句 格式: try: 語句t except 錯誤表示碼 as e: 語句1 except 錯誤表示碼 as e: 語句2 …… except 錯誤表示碼 as e: 語句n else: 語句e 做用:用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常並處理 邏輯: 一、若是try後的「語句t」執行時發生異常,就調回到執行try並執行一個匹配該異常的except子句,異常處理結束,就結束整個try語句(除非處理異常時又引起新的異常) 二、果try後的「語句t」執行時發生異常,可是卻沒有匹配的except子句,異常提交到上一層try,或者到程序的最上層 三、若是try後的「語句t」執行時沒有發生異常,就不會匹配except,若是有else語句,則執行語句e,最後結束整個try語句 '''
# try:
# try:
# print(10 / 1)
# except AttributeError as e:
# print(str(e))
# else:
# print("沒有異常")
# except ZeroDivisionError as e:
# print("-----------")
# print("sunck is a good man")

# 特殊使用
#一、使用except而不帶任何錯誤類型,捕獲任何異常
# try:
# print(10 / 1)
# except:
# print("有問題")
# else:
# print("沒有異常")

#二、使用except而帶有多種異常類型,同時匹配多種異常
# try:
# print(10 / 1)
# except (AttributeError, ZeroDivisionError) as e:
# print(str(e))
# else:
# print("沒有異常")


#使用注意項
#一、python中的錯誤其實是類,全部的錯誤類型都繼承自BaseException,因此在使用時注意父類會將子類異常一網打盡
# try:
# print(10 / 0)
# except BaseException as e:
# print("----------1")
# except ZeroDivisionError as e:
# print("----------2")

#二、跨越多層調用,main裏調用f2,f2裏調用f1,在f1裏出錯,只要在main裏捕獲就能夠處理了
# def f1(s):
# return 10 / s
# def f2(s):
# return f1(s) + 1
# def main():
# try:
# f2(0)
# except ZeroDivisionError as e:
# print(str(e))
# main()
# print("sunck is a good man")


'''try……except……finally語句 做用:不管try語句塊是否發生異常,都將執行finally子句 格式: try: 語句t except 錯誤表示碼 as e: 語句1 except 錯誤表示碼 as e: 語句2 …… except 錯誤表示碼 as e: 語句n finally: 語句f '''
try:
    print(10 / 1)
except ZeroDivisionError as e:
    print("----------2")
finally:
    print("**********")

複製代碼

調試(print)

# -*- coding:utf-8 -*-

# 寫好的代碼能直接運行的機率很是小,總會在不經意間出現更重各樣的BUG,有的BUG很簡單,看看錯誤提示就能修改,可是有的BUG分複雜,須要一些調試手段來發現並解決

def func(x):
    print("x = %d"%x)
    return 10 / x

func(0)


# 缺點:未來得刪除調試的print,運行結果也會包含一些垃圾信息

複製代碼

調試(斷言)

# -*- coding:utf-8 -*-

# 使用:凡是用print來輔助調試的 地方,均可以換成斷言(assert)語句

#邏輯:當程序執行到assert語句時,首先計算第一個表達式的值,若是表達式的值爲真則繼續向下執行,不然斷言失敗,assert語句會拋出AssertionError異常,異常的信息爲第二個表達式的值

#缺點:若是將全部的print換成assert也好不到哪裏去

#優勢:在啓動程序時能夠經過命令添加-O參數能夠關閉assert

def func(x):
    assert x != 0, "x is zero"
    return 10 / x

func(0)

複製代碼

調試(logging)

# -*- coding:utf-8 -*-
import logging
#配置輸出級別
logging.basicConfig(level=logging.INFO)
''' CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 '''

#使用:把print替換爲logging也能夠,和assert相比logging不會拋出錯誤,而且能夠輸出到文件


def func(x):
    logging.info("x = %d"%x)
    return 10 / x

func(0)

複製代碼

調試(pdb)

# -*- coding:utf-8 -*-

#使用:python的調試器,讓程序已單步方式容許(一句一句的運行),能夠隨時查看運行動態

#以pdb方式調試代碼,須要黑屏啓動 python -m pdb 文件名


'''調試命令 n:單步執行代碼 p 變量名:查看變量 q:退出調試 '''

#缺點:麻煩,若是有10000代碼,認爲錯誤可能出如今9000行,須要運行到9000行才行

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = 0
print(10 / n)
print("-------------8")
print("-------------9")

複製代碼

調試(pdb的自定義開始斷點)

# -*- coding:utf-8 -*-

#使用:python的調試器,讓程序已單步方式容許(一句一句的運行),能夠隨時查看運行動態

#以pdb方式調試代碼,須要黑屏啓動 python -m pdb 文件名


'''調試命令 n:單步執行代碼 p 變量名:查看變量 q:退出調試 '''

#缺點:麻煩,若是有10000代碼,認爲錯誤可能出如今9000行,須要運行到9000行才行

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = 0
print(10 / n)
print("-------------8")
print("-------------9")

複製代碼

調試(IDE斷點)python

# -*- coding:utf-8 -*-

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = "0"
n = int(n)
print(10 / n)
print("-------------8")
print("-------------9")

複製代碼

文檔測試

# -*- coding:utf-8 -*-
import doctest
#該模塊能夠直接提取註釋中的代碼並執行測試


def mySum(x, y):
    #doctest嚴格按照python交互式命令的輸入和輸出來判斷測試結果是否正確
    ''' >>> print(mySum(1, 2)) 3 '''
    return x + y
print("sunck good")
doctest.testmod()

複製代碼

對文件的操做

讀文件

# -*- coding:utf-8 -*-
''' 過程: 一、找到文件 二、打開文件 三、讀取文件內容 四、關閉文件 '''


#找到文件、打開文件
filePath = r"C:\Users\xlg\Desktop\gp01\day12\code\sunck.txt"
''' 原型: def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True) 參數: file:要打開文件的路徑 mode:打開方式 encoding:編碼方式 errors:錯誤處理 返回值: 文件描述符(本質就是一個引用),經過文件描述符能夠操做文件 '''
'''打開方式 r 以只讀方式打開文件,文件的引用將會放在文件開頭 rb 以二進制格式打開只讀文件,文件的引用將會放在文件開頭 r+ 以讀寫方式打開文件,文件的引用將會放在文件開頭 w 以只寫方式打開文件,若是該文件已經存在,則將其內容覆蓋,若是不存在則會建立文件 wb 以二進制格式打開只寫文件,若是該文件已經存在,則將其內容覆蓋,若是不存在則會建立文件 w+ 以讀寫方式打開文件,若是該文件已經存在,則將其內容覆蓋,若是不存在則會建立文件 a 打開一個文件用於追加,若是該文件已經存在,文件的引用將會放在文件的末尾,也就是說新的內容添加到已有內容以後。果不存在則會建立文件進行寫入 a+ 打開一個文件用於讀寫,若是該文件已經存在,文件的引用將會放在文件的末尾,也就是說新的內容添加到已有內容以後。果不存在則會建立文件進行寫入 '''

#打開普通文件
fp = open(filePath, "r")
#打開二進制文件
# fp = open(filePath, "rb")
#打開指定編碼格式的文件
# fp = open(filePath, "rb", encoding="GBK")
#錯誤處理:直接忽略
# fp = open(filePath, "rb", encoding="utf-8", errors="ignore")




#讀取文件內容

#一、讀取文件所有內容
# str1 = fp.read()
# print(str1)

#二、讀取指定字節數
# str2 = fp.read(12)
# print("*"+str2+"*")

#三、讀取整行,包括"\n"字符
# str3 = fp.readline()
# print(str3+"*")

#四、讀取指定字節數
# str3 = fp.readline(12)
# print("*"+str3+"*")

#五、讀取全部行並返回列表
# list4 = fp.readlines()
# print(list4)
# print(type(list4))

#讀取文件的原理是從文件描述符的位置向後讀取
print("-------------", fp.tell())
fp.read()
#查看文件描述符的位置
print("-------------", fp.tell())
#修改文件描述符的位置
fp.seek(1)
str5 = fp.read(12)
print("*"+str5+"*")
str6 = fp.read(2)
print("*"+str6+"*")


#關閉文件:文件使用完後必須關閉,由於文件對象會佔用操做系統的資源,而且操做系統同一時間能打開的文件的數量是有限的
fp.close()
複製代碼

讀文件的完整過程

# -*- coding:utf-8 -*-


try:
    fp = open("sunck.txt", "r")
    #操做文件
finally:
    if fp:
        fp.close()
複製代碼

讀文件的簡寫方式

# -*- coding:utf-8 -*-


with open("sunck.txt", "r") as fp:
    print(fp.read())
複製代碼

寫文件

# -*- coding:utf-8 -*-
import time

'''寫文件過程 一、找到文件 二、打開文件 三、將內容寫入緩衝區,此時內容沒寫寫入文件 四、刷新緩衝區,直接把緩衝區的數據馬上寫入文件 刷新緩衝區的方式: a、程序結束 b、關閉文件 c、手動刷新 d、遇到\n e、緩衝區滿了 五、關閉文件 '''

filePath = "sunck.txt"
fp = open(filePath, "a")

# 將內容寫入緩衝區
fp.write("sunck is a good man!")
# 刷新緩衝區
fp.flush()
# time.sleep(5)

fp.close()



#簡單方式
# with open("sunck.txt", "w") as fp1:
# fp1.write("asd")

複製代碼

編碼與解碼

# -*- coding:utf-8 -*-

# 編碼
with open("sunck.txt", "wb") as f1:
    info = "sunck is a nice man!凱"
    info = info.encode("utf-8")
    print(info)
    f1.write(info)


# 解碼
with open("sunck.txt", "rb") as f2:
    info = f2.read()
    print(info)
    print(type(info))
    info = info.decode("utf-8")
    print(info)
    print(type(info))

複製代碼

StringIO和BytesIO

# -*- coding:utf-8 -*-
from io import StringIO
from io import BytesIO

#StringIO
#做用:數據的讀寫不必定都是文件,也能夠在內存中讀寫,做用是在內存中讀寫字符串
#寫
# fp = StringIO()
# fp.write("sunck")
# fp.write(" ")
# fp.write("is")
# fp.write(" ")
# fp.write("a")
# fp.write(" ")
# fp.write("good")
# fp.write(" ")
# fp.write("man!")
# #獲取寫入的內容
# info = fp.getvalue()
# print(info)


#讀
# fp = StringIO("good\nnice\nhandsome\n")
# print(fp.read())
# print(fp.readline())



#BytesIO
#做用:StringIO只能操做字符串,BytesIO能夠操做二進制數據,做用是在內存中讀寫bytes
#寫
# fp = BytesIO()
# fp.write("凱哥".encode("utf-8"))
# print(fp.getvalue())

# 讀
# fp = BytesIO(b'\xe5\x87\xaf\xe5\x93\xa5')
# print(fp.read().decode("utf-8"))

複製代碼

os模塊

# -*- coding:utf-8 -*-
import os

#做用:包含了廣泛的操做系統功能,提供了很是豐富的方法來處理文件和目錄


#使用


# 操做系統的類型
# nt Windows
# posix Linux、Unix
print(os.name)

# 獲取詳細的系統信息,linux、Unix下使用
# print(os.uname())

# 獲取系統中的環境變量
print(os.environ)
# 獲取指定環境變量的值
print(os.environ.get("ALLUSERSPROFILE"))

# 放回當前目錄 .
print(os.curdir)

# 獲得當前工做目錄的絕對路徑
print(os.getcwd())

# 返回指定目錄下的全部文件和目錄 listdir([path]),沒有path返回當前工做目錄下的
print(os.listdir(r"C:\Users\xlg\Desktop\gp01"))

#建立指定目錄
# os.mkdir(r"C:\Users\xlg\Desktop\gp01\day14")

#刪除目錄
# os.rmdir(r"C:\Users\xlg\Desktop\gp01\day14")

#獲取文件屬性
# print(os.stat(r"C:\Users\xlg\Desktop\gp01\一、基礎內容簡介.txt"))

#重命名
# os.rename(r"C:\Users\xlg\Desktop\gp01\day13\code\sunck.txt",r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt")

#刪除普通文件
# os.remove(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt")

#運行shell命令
# os.system("notepad")
# os.system("shutdown -s -t 10")
# os.system("shutdown -a")




#操做文件和目錄的函數一部分放在os模塊中,還有一部分放在os.path中

#返回指定路徑的絕對路徑
print(os.path.abspath("."))
#拼接路徑
print(os.path.join(r"C:\Users\xlg\Desktop\gp01\day13\abc", "kaige.txt"))
#拆分路徑
print(os.path.split(r"C:\Users\xlg\Desktop\gp01\day13\abc\kaige.txt"))
#獲取文件擴展名
print(os.path.splitext(r"C:\Users\xlg\Desktop\gp01\day13\abc\kaige.txt"))
#判斷是不是目錄(得存在),是返回True, 不然返回False,
print(os.path.isdir(r"C:\Users\xlg\Desktop\gp01\day13\code"))
#判斷普通文件是否存在,存在返回True, 不然返回False
print(os.path.isfile(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))
#判斷文件和目錄是否存在
print(os.path.exists(r"C:\Users\xlg\Desktop\gp01\day13\abc"))
#判斷是不是絕對路徑,(不管是否存在)
print(os.path.isabs(r"C:\Users\xlg\Desktop\gp01\day13\abc"))


#獲取文件大小
print(os.path.getsize(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))



#獲取文件名
print(os.path.basename(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))
#獲得文件路徑
print(os.path.dirname(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))

複製代碼

list、tuple、dict、set的文件操做

# -*- coding:utf-8 -*-

# 持久保存對象,將list、tuple、dict、set等數據進行序列化存儲到文件
import pickle

# users = {"666666":{"name":"sunck","idCard":"666666","cards":{"1":{"cardId":"1","passwd":"1","money":"1"}}}}
# with open("users.txt", "wb") as fp:
# pickle.dump(users, fp)


# with open("users.txt", "rb") as fp:
# users = pickle.load(fp)
# print(users)
# print(type(users))

複製代碼

遞歸、深度遍歷、廣度遍歷算法

遞歸

# -*- coding:utf-8 -*-

''' 遞歸: 一、自身調用自身造成遞歸 二、兩個函數相互調用造成遞歸 遞推: '''


#遞歸調用:一個函數,調用自身,稱爲遞歸調用
#遞歸函數:一個會調用自身的函數稱爲遞歸函數
#注意:凡是循環能幹的事,遞歸都能幹

''' 遞歸三步走 一、寫出臨界條件 二、假設當前函數已經能用,調用自身計算上一次的結果,在求出本次結果 三、找這一次和上一次的關係 '''


#在之後的開發中儘可能避免使用遞歸,容易形成內存泄露,效率也會偏低

#1 + 2 + 3 + 4 + 5
def func(num):
    if num == 1:
        return 1
    return func(num - 1) + num

print(func(5))

''' func(5) func(4) + 5 func(3) + 4 + 5 func(2) + 3 + 4 + 5 func(1) + 2 + 3 + 4 + 5 1 + 2 + 3 + 4 + 5 '''

複製代碼

遞歸遍歷目錄

# -*- coding:utf-8 -*-

import os
def traverseDir(path, treeShow = ""):
    filesList = os.listdir(path)
    for filename in filesList:
        absPath = os.path.join(path, filename)
        if os.path.isdir(absPath):
            print(treeShow+"目錄:"+filename)
            traverseDir(absPath, treeShow + " ")
        else:
            print(treeShow+"文件:"+filename)
traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

複製代碼

棧模擬遞歸遍歷目錄(深度遍歷)

# -*- coding:utf-8 -*-


def traverseDir(path):
    import os
    myStack = []

    myStack.append((path,0))

    while len(myStack) != 0:
        #出棧
        item = myStack.pop()
        filePath = item[0]
        num = item[1]
        treeShow = " " * num
        filesList = os.listdir(filePath)
        for fileName in filesList:
            absPath = os.path.join(filePath, fileName)
            if os.path.isdir(absPath):
                #壓棧
                print(treeShow + "目錄:" + fileName)
                myStack.append((absPath, num+1))
            else:
                print(treeShow + "文件:" + fileName)

traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

複製代碼

隊列模擬遞歸遍歷目錄(廣度遍歷)

# -*- coding:utf-8 -*-


def traverseDir(path):
    import os
    from collections import deque

    queue = deque([])

    #進隊
    queue.append((path, 0))

    while len(queue) != 0:
        #出隊
        item = queue.popleft()
        filePath = item[0]
        num = item[1]
        treeShow = " " * num
        filesList = os.listdir(filePath)

        for fileName in filesList:
            absPath = os.path.join(filePath, fileName)
            if os.path.isdir(absPath):
                #進隊
                print(treeShow + "目錄:" + fileName)
                queue.append((absPath, num + 1))
            else:
                print(treeShow + "文件:" + fileName)



traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

複製代碼

正則

爲何使用正則

# -*- coding:utf-8 -*-

#輸入一串字符串,判斷是不是手機號碼

def isPhone(phone):
    # 全都是數字字符
    # 長度爲11
    # 以130、131等開頭
    pass


# 使用正則會讓這個問題簡單化

複製代碼

re模塊概述

# -*- coding:utf-8 -*-


''' python自1.5版本起增長了re模塊,該模塊提供了Perl風格的正則表達式模式 re模塊使python語言擁有了所有的正則表達式功能 三個函數: match() search() findall() '''

複製代碼

match函數

# -*- coding:utf-8 -*-
import re

r''' 原型:match(pattern, string, flags=0) 功能:嘗試從字符串string的起始位置匹配一個pattern模式,若是匹配成功,返回正則對象,不然返回None。 返回的正則對象中有: start():匹配到的開始索引、end():匹配到的結束索引、string:匹配的字符串、groups():返回括號中匹配到的數據(單個)、span():返回匹配到的起始索引、group():返回匹配到的總體、endpos() 參數: pattern:匹配的正則表達式 string:要匹配的字符串 flags:標誌位,用於控制正則表達式的匹配方式(是否大小寫、是否多行匹配等等) re.I:使匹配對大小寫不敏感 re.L:作本地化識別匹配 re.M:多行匹配,影響^和$ re.S:使.匹配包括換行符在內的全部字符 re.U:根據Unicode字符集解析字符,影響\w、\W、\b、\B re.X:經過給予咱們功能靈活的格式以便更好的理解正則表達式 '''

print(re.match("www", "www.sunck.wang"))
print(re.match("www", "sunck.wangwww"))
print(re.match("www", "Www.sunck.wang", re.I))
ret = re.match("www", "www.sunck.wang")
print(ret.span())

複製代碼

search函數

# -*- coding:utf-8 -*-

import re

''' 原型:search(pattern, string, flags=0) 功能:掃描整個字符串string,並返回第一個成功的匹配 參數: '''
print(re.search("www", "www.sunck.wang"))
print(re.search("www", "awww.sunck.wangwww"))

複製代碼

findall函數

# -*- coding:utf-8 -*-
import re

''' 原型:findall(pattern, string, flags=0) 功能:掃描整個字符串string並返回結果的列表 '''
print(re.findall(r"ww[12345]","ww1.suwwwnck.wwwaaang"))

返回值:
若是成功,返回匹配到數據的列表([('ww', 'w'), ('ww', 'w')]),若是不成功,返回空鏈表
# ww1 ww2 ww3 ww4 ww5

複製代碼

正則表達式元字符

# -*- coding:utf-8 -*-
import re

# 一、匹配單個字符與數字
''' . 匹配除換行符之外的任意字符,當flags被指定爲re.S時能夠匹配包含換行符之內的全部字符,若是沒有指定,那麼不包含換行符[.\n] [] 裏面是字符的集合,匹配[]裏面任意一個字符 [0123456789] 匹配任意一個數字字符 [0-9] 匹配任意一個數字字符 [a-z] 匹配任意一個小寫英文字母字符 [A-Z] 匹配任意一個大寫英文字母字符 [a-zA-Z] 匹配任意一個字母字符 [a-zA-Z0-9] 匹任意一個數字或字母字符 [^sunck] []裏的^稱爲脫字符,表示非,匹配不在[]裏的任意一個字符。匹配除了 "s" "u" "n" "c" "k"之外任意一個字符 \d 匹配任意一個數字字符 [0-9] \D 匹配任意一個非數字符 [^0-9] \w 匹配字母、下劃線、數字 [0-9a-zA-z_] \W 匹配非字母、下劃線、數字 [^0-9a-zA-z_] \s 匹配空白符(空格、換頁、換行、回車、製表等) [ \f\n\r\t] \S 匹配非空白符 [^ \f\n\r\t] '''








# 二、錨字符
''' ^ 行首匹配,和[]中的^不是一個意思 $ 行尾匹配 '''
# print(re.search(r"^sunck$", "sunck"))


# 二、邊界字符
r''' \A 匹配字符串開始,和^的區別是\A只匹配整個字符的開頭,即便在re.M模式下,也不會匹配其它的行首 \Z 匹配字符結尾,和$的區別是\Z只匹配整個字符的結尾,即便在re.M模式下,也不會匹配其它的結尾 \b 匹配一個單詞的邊界,指單詞和空格的位置 \B 匹配非單詞邊界, '''
s = '''sunck is a good man sunck is a nice man sunck is a cool man '''
# print(re.findall(r"\Asunck", s, re.M))
# print(re.findall(r"ck\b", "sunck"))
# print(re.findall(r"ck\b", "suckn"))
# print(re.findall(r"ck\B", "sunck"))
# print(re.findall(r"ck\B", "suckn"))






# 四、匹配多個字符
'''如下使用的x、y、z均爲假設的普通字符,n、m表示一個數字,不是正則表達是的元字符 (xyz) 匹配括號內的xyz(做爲一個總體去匹配) x? 匹配0個或1個x,非貪婪匹配 x* 匹配0個或任意多個x x+ 匹配至少一個x x{n} 匹配肯定n個x,n是非負整數 x{n,} 匹配至少n個x x{n,m} 匹配至少n個,最多m個x x|y |表示或,匹配x或y '''
print(re.findall(r"(sunck)", "sunck is a good man!sunck is a ncie man"))
print(re.findall(r"a?", "abbbaabbaaa"))
print(re.findall(r"a*", "aaa"))
print(re.findall(r"P|python", "pythonaaaPython"))

複製代碼

切分字符串

# -*- coding:utf-8 -*-
import re


str1 = "sunck is a good man!"
# print(str1.split(" "))

print(re.split(r" +", str1))

複製代碼

finditer函數

# -*- coding:utf-8 -*-
import re

''' 原型:finditer(pattern, string, flags=0) 做用:相似findall,返回一個迭代器 區別:findall返回全部匹配的字符,並存爲一個列表,若是數據過多,佔用內存。而finditer並非直接返回找到的全部字符從,而是返回一個迭代器,能夠經過next迭代 '''
str1 = "sunck is a good man! sunck is a good man"
res = re.finditer(r"(sunck)", str1)
print(res)
print(type(res))
for x in res:
    print(x)

複製代碼

字符串的替換和修改

# -*- coding:utf-8 -*-

import re

''' sub(pattern, repl, string, count=0, flags=0) subn(pattern, repl, string, count=0, flags=0) 做用:在目標字符串string中查找匹配的pattern模式字符,在把它們替換成指定的repl字符串,能夠指定最多替換count次,不然替換全部 參數: pattern:正則表達式 repl:指定用來替換的字符串 string:目標字符串 count:最多替換次數 flags: 區別:sub返回一個被替換的字符串,subn返回一個元組,元組的第一個元素爲被替換的字符串,第二個元素爲發生了多少次替換 '''
str1 = "sunck is a good man!sunck is a nice man!sunck is a cool man"
print(re.sub(r"(sunck)", "kaige", str1))
print(re.subn(r"(sunck)", "kaige", str1))

複製代碼

分組

# -*- coding:utf-8 -*-
import re

''' 概念:除了簡單的判斷是否匹配以外,正則表達式還有提取子串的功能,用()表示的就是要提取的分組 '''

 
#組的排序:從外到內,從左到右
print(m)
# 使用組序號獲取匹配的字符串,0表示原數據
print(m.group(0))
#根據名字獲取組內容
print(m.group("quhao"))
print(m.group(1))
print(m.group("phone"))
print(m.group(2))
# 查看匹配的各組的數據
print(m.groups())

複製代碼

編譯

# -*- coding:utf-8 -*-
import re

''' 概念:當在python中使用正則表達式時,re模塊會作兩件事情,一件是編譯正則表達式,若是表達式的字符串自己不合法,會報錯。一件是用編譯後的正則表達式取匹配字符串 優勢:若是一個正則表達式要使用幾千遍,每一次都會編譯,處於效率的考慮進行正則表達式的編譯,這樣就不用每次都編譯,節省了編譯時的時間,提高了效率 '''

#編譯正則表達式,獲得的是一個正則表達式對象
re_phone = re.compile(r"(?P<quhao>\d{3})-(?P<phone>\d{8})", re.I)



print(re_phone.findall("010-09876543aa010-98789098"))
''' findall(self, string, pos=0, endpos=-1) finditer(self, string, pos=0, endpos=-1) match(self, string, pos=0, endpos=-1) search(self, string, pos=0, endpos=-1) '''


複製代碼

貪婪匹配

# -*- coding:utf-8 -*-
import re

''' 概念:匹配儘量多的字符 '''


print(re.match(r"^(\d+?)(0*)$", "120345000").groups())


'''儘量匹配少的字符串 *? +? ?? '''


print(re.findall(r"//*.*/*/", r"/* part1 */ /* part2 */"))
res = re.findall(r"//*.*?/*/", r"/* part1 */ /* part2 */")
print(res)


複製代碼

多任務

多任務原理

# -*- coding:utf-8 -*-


''' 什麼叫多任務:操做系統能夠同時運行多個任務,現代的操做系統好比Windows、Mac OS X、Linux、Unix等都是支持多任務的系統 '''

#單核CPU實現多任務的原理:找圖去看



#多核CPU實現多任務的原理:找圖

# 爲何要實現多任務:想效率高,不卡頓


'''實現多任務的方式 一、多進程模式:啓動多個進程,每一個進程雖然只有一個線程,可是多個進程能夠一塊兒執行多個任務 二、多線程模式:啓動一個進程,在一個進程的內部啓動多個線程,這樣多個線程也能夠一塊兒執行多個任務 三、多進程+多線程:啓動多個進程,每一個進程再啓動多個線程 四、協程 五、多進程+協程 '''


複製代碼

進程的概念

# -*- coding:utf-8 -*-

''' 什麼是進程:進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操做系統結構的基礎。在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體 對於操做系統來講,一個任務就是一個進程。比方說打開瀏覽器就是啓動一個瀏覽器的進程,在打開一個記事本就啓動一個記事本進程,若是打開兩個記事本就啓動兩個記事本進程。 '''


複製代碼

單任務現象

# -*- coding:utf-8 -*-

from time import sleep


def run():
    while True:
        print("sunck is a good man!")
        sleep(1)

if __name__ == "__main__":
    while True:
        print("kaige is a nice man")
        sleep(1.2)
    # 不會執行到run方法,只有上面的while循環結束才行
    run()


複製代碼

啓動進程實現多任務

# -*- coding:utf-8 -*-



from multiprocessing import Process
from time import sleep

''' multiprocessing模塊 一、跨平臺的多進程模塊 二、提供了一個Process類表明一個進程對象 '''

def run(name, description):
    while True:
        print("%s is a %s man!"%(name, description))
        sleep(1)

if __name__ == "__main__":
    #程序啓動的進程稱爲主進程(父進程)

    #建立進程(子進程)
    p = Process(target=run, args=("sunck", "handsome"))
    #啓動子進程
    p.start()

    while True:
        print("kaige is a nice man")
        sleep(1.2)


複製代碼

父子進程的前後順序

# -*- coding:utf-8 -*-

from multiprocessing import Process
from time import sleep

def run():
    print("啓動子進程")
    sleep(3)
    print("結束子進程")

def run2():
    print("啓動子進程2")
    sleep(3)
    print("結束子進程2")

if __name__ == "__main__":
    print("啓動主進程")

    p = Process(target=run)
    p.start()

    p2 = Process(target=run2)
    p2.start()

    #主進程的結束不能影響子進程,隨意能夠等待子進程結束在結束主進程
    #等待子進程結束,才能繼續執行主進程
    #後期主進程主要作的是調度相關的工做,不具體負責業務邏輯
    p.join()
    p2.join()
    print("結束主進程")


複製代碼

全局變量在多個進程中不能共享

# -*- coding:utf-8 -*-

from multiprocessing import Process
from time import sleep

money = 10

def run1():
    print("啓動子進程1")
    global money
    print("run1---1-", money)  #0
    sleep(3)
    print("run1---2-", money)  #20 真實爲0
    money = 30
    print("run1---3-", money)  #30
    print("結束子進程2")

def run2():
    print("啓動子進程2")
    global money
    print("run2---1-", money) #0
    sleep(1)
    money = 20
    print("run2---2-", money) #20
    print("結束子進程2")

if __name__ == "__main__":
    print("啓動主進程")

    #在建立子進程時會將主進程的資源拷貝到子進程中,子進程單獨有一份主進程中的數據。相互不影響
    p1 = Process(target=run1)
    p2 = Process(target=run2)
    p1.start()
    p2.start()

    p1.join()
    p2.join()
    print("money = %d"%money) #30 真實爲0
    print("結束主進程")


複製代碼

啓動大量子進程

# -*- coding:utf-8 -*-
import os
import time
import random

from multiprocessing import Process, Pool

def run(name):
    # os.getpid()獲取當前進程的進程ID
    print("子進程%s啓動--%s"%(name, os.getpid()))
    t1 = time.time()
    time.sleep(random.random()*5)
    t2 = time.time()
    print("子進程%s結束--%s--耗時%.2f" % (name, os.getpid(), t2-t1))

if __name__ == "__main__":
    print("啓動父進程")

    #進程池
    #表示能夠同時執行的進程數量
    #因爲Pool的默認值爲CPU的核心數量,若是有4個核心,則至少須要子進程才能看到等待的效果
    pool = Pool(4)
    for i in range(3):
        # 建立進程放入進程池中贊成管理
        pool.apply_async(run, args=(i,))


    # 進程池對象調用join以前必須先調用close,調用close以後就不能向進程池中添加進程了
    pool.close()
    #Pool對象調用join方法,會等待全部子進程結束在執行主進程
    pool.join()

    print("結束父進程")


複製代碼

進程封裝

class KaigeProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name
    #當對象調用start方法時,默認調用run方法
    def run(self):
        print("子進程(%s--%s)啓動(父進程:%s)"%(self.name, os.getpid(),os.getppid()))
        print("kaige is a good man")
        time.sleep(2)
        print("子進程(%s--%s)結束(父進程:%s)" % (self.name, os.getpid(), os.getppid()))


複製代碼

多進程遍歷目錄

# -*- coding:utf-8 -*-
import os
import time
from multiprocessing import Pool

# path = r"C:\Users\xlg\Desktop\gp01\day14\file"
# filesList = os.listdir(path)
# t1 = time.time()
# for fileName in filesList:
# absPath = os.path.join(path, fileName)
# if os.path.isdir(absPath):
# files = os.listdir(absPath)
# for item in files:
# print(os.path.join(absPath, item))
# t2 = time.time()
# print(t2-t1)


def run(path):
    files = os.listdir(path)
    for item in files:
        print(os.path.join(path, item))
if __name__ == "__main__":
    path = r"C:\Users\xlg\Desktop\gp01\day14\file"
    filesList = os.listdir(path)

    t1 = time.time()
    pool = Pool(5)
    for fileName in filesList:
        absPath = os.path.join(path, fileName)
        pool.apply_async(run, args=(absPath,))
    pool.close()
    pool.join()
    t2 = time.time()
    print(t2 - t1)


複製代碼

進程間通訊

# -*- coding:utf-8 -*-

from multiprocessing import Process, Queue
import time
import random

'''進程間通訊 有名管道 無名管道 隊列 共享內存 信號 信號量 '''

#
def produce(q):
    print("啓動produce子進程……")
    time.sleep(5)
    for value in ["good", "nice", "cool", "handsome"]:
        print("將%s放入隊列"%value)
        q.put(value)
        time.sleep(random.random())
    print("結束produce子進程……")

#
def customer(q):
    print("啓動customer子進程……")
    while True:
        print("消費者等待數據")
        value = q.get(True)
        print("消費者消費%s條數據"%value)
    print("結束customer子進程……")


if __name__ == "__main__":

    q = Queue()

    pro = Process(target=produce, args=(q,))
    cus = Process(target=customer, args=(q,))
    pro.start()
    cus.start()

    pro.join()
    #cus進程裏是死循環,沒法等待它的結束,只能強制結束該子進程
    cus.terminate()

    print("END")


複製代碼

什麼是線程

# -*- coding:utf-8 -*-


''' 線程: 線程,有時被稱爲輕量進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程本身不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的所有資源。一個線程能夠建立和撤消另外一個線程,同一進程中的多個線程之間能夠併發執行。因爲線程之間的相互制約,導致線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。就緒狀態是指線程具有運行的全部條件,邏輯上能夠運行,在等待處理機;運行狀態是指線程佔有處理機正在運行;阻塞狀態是指線程在等待一個事件(如某個信號量),邏輯上不可執行。每個程序都至少有一個線程,若程序只有一個線程,那就是程序自己。 線程是程序中一個單一的順序控制流程。進程內有一個相對獨立的、可調度的執行單元,是系統獨立調度和分派CPU的基本單位指令運行時的程序的調度單位。在單個程序中同時運行多個線程完成不一樣的工做,稱爲多線程 多線程:多線程(英語:multithreading),是指從軟件或者硬件上實現多個線程併發執行的技術。具備多線程能力的計算機因有硬件支持而可以在同一時間執行多於一個線程,進而提高總體處理性能。具備這種能力的系統包括對稱多處理機、多核心處理器以及芯片級多處理(Chip-level multithreading)或同時多線程(Simultaneous multithreading)處理器。 [1] 在一個程序中,這些獨立運行的程序片斷叫做「線程」(Thread),利用它編程的概念就叫做「多線程處理(Multithreading)」。具備多線程能力的計算機因有硬件支持而可以在同一時間執行多於一個線程(臺灣譯做「執行緒」),進而提高總體處理性能 '''


複製代碼

啓動線程實現多任務

# -*- coding:utf-8 -*-

#模塊
''' _thread模塊:低級模塊 threading模塊:高級模塊,對_thread進行了封裝 '''

import threading
import random
import time

def run1(num):
    print("啓動%s子線程1-----%s"%(threading.current_thread().name, num))
    time.sleep(random.random()*5)
    print("結束%s子線程1-----%s" % (threading.current_thread().name, num))

def run2(num):
    print("啓動%s子線程2-----%s" % (threading.current_thread().name, num))
    time.sleep(random.random() * 5)
    print("結束%s子線程2-----%s" % (threading.current_thread().name, num))


if __name__ == "__main__":
    # threading.current_thread()獲得當前線程對象
    # 主線程的名字默認爲MainThread
    print("主線程%s啓動……" % threading.current_thread().name)

    #建立線程
    th1 = threading.Thread(target=run1, args=(1,), name="th1")
    th2 = threading.Thread(target=run2, args=(2,), name="th2")

    #啓動
    th1.start()
    th2.start()

    #等待子線程結束
    th1.join()
    th2.join()

    print("主線程%s結束……" % threading.current_thread().name)


複製代碼

線程間共享數據

# -*- coding:utf-8 -*-

#多線程和多進程最大的不一樣在於,多進程中,同一個全局變量,每一個子進程各自有一份拷貝,互不影響。而在多線程中,全部變量都由線程共享,因此任何一個變量均可以被任意線程所修改。所以,多個線程同時改變一個變量,容易把內容改亂了



import threading
import random
import time

money = 0
def changeMoney(n):
    global money
    money = money + n
    money = money - n

def run1(num):
    for i in range(1000000):
        changeMoney(num)

def run2(num):
    for i in range(1000000):
        changeMoney(num)


if __name__ == "__main__":
    #建立線程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #啓動
    th1.start()
    th2.start()

    #等待子線程結束
    th1.join()
    th2.join()

    print("money = %d"%money)


複製代碼

線程鎖解決數據混亂

# -*- coding:utf-8 -*-


# 問題:兩個線程同時一寸一取,可能形成變量值的不對,咱們必須保證一個線程在修改money的時候,其餘的線程必定不能修改


#後期在線程中對變量上鎖,可是千萬要注意釋放鎖(本身的鎖本身放),不然會形成死鎖

import threading
import random
import time

lock = threading.Lock()

money = 0
def changeMoney(n):
    global money
    money = money + n
    money = money - n

def run1(num):
    for i in range(1000000):
        #獲取線程鎖,若是已上鎖,則阻塞等待鎖的釋放
        lock.acquire()
        try:
            changeMoney(num)
        finally:
            #釋放鎖
            lock.release()

def run2(num):
    for i in range(1000000):
        with lock:
            changeMoney(num)


if __name__ == "__main__":
    #建立線程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #啓動
    th1.start()
    th2.start()

    #等待子線程結束
    th1.join()
    th2.join()

    print("money = %d"%money)


複製代碼

ThreadLocal

# -*- coding:utf-8 -*-


import threading
import random
import time

# 建立全局ThreadLocal對象
# 每一個線程獨立的存儲空間
# 每一個Thread對它均可以讀寫屬性操做,可是互不影響
local = threading.local()


def run1(num):
    time.sleep(1)
    local.money = 2
    print("1-------------", local.money,id(local.money))


def run2(num):
    time.sleep(3)
    local.money = 3
    print("3-------------", local.money,id(local.money))



if __name__ == "__main__":
    #建立線程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #啓動
    th1.start()
    th2.start()

    #等待子線程結束
    th1.join()
    th2.join()

    # print("money = %d"%money)

複製代碼

定時線程

# -*- coding:utf-8 -*-

import time
import threading


def run():
    print("sunck is a good man")


if __name__ == "__main__":
    # 常常啓動5秒後在執行,不會阻塞主線程
    th = threading.Timer(5, run)

    th.start()

    th.join()

複製代碼

線程通訊

# -*- coding:utf-8 -*-

import threading
import time


def func():
    event= threading.Event()
    def run():
        for i in range(10):
            #阻塞
            event.wait()
            #重置
            event.clear()
            print("--------------" + str(i))
    th = threading.Thread(target=run)
    th.start()
    return event

event = func()


for i in range(10):
    event.set()
    time.sleep(1)
print("END")

複製代碼

生產者與消費者

# -*- coding:utf-8 -*-


import threading
import queue
import random
import time

def produce(q, index):
    while True:
        num = random.randint(0, 1000000)
        q.put("生產者%s產生數據:%d"%(index, num))
        print("生產者%s產生數據:%d"%(index, num))
        time.sleep(1)
    # 完成任務
    q.task_done()


def customer(q, index):
    while True:
        item = q.get()
        if item is None:
            break
        print("消費者%s獲取到:%s"%(index, item))
        time.sleep(4)
    # 完成任務
    q.task_done()


if __name__ == "__main__":
    q = queue.Queue(10)

    arr = []

    #建立三個生產者
    for i in range(3):
        th = threading.Thread(target=produce, args=(q, i))
        th.start()
        arr.append(th)

    # 建立5個消費者
    for j in range(5):
        th = threading.Thread(target=customer, args=(q, j))
        th.start()
        arr.append(th)

    for th in arr:
        th.join()
    print("END")

複製代碼

線程調度

# -*- coding:utf-8 -*-

# -*- coding:utf-8 -*-


import threading
import time

#線程條件變量
cond = threading.Condition()

def run1():
    with cond:
        for i in range(0, 10, 2):
            print(threading.current_thread().name+"---"+str(i))
            time.sleep(1)
            cond.wait()
            cond.notify()

def run2():
    with cond:
        for i in range(1, 10, 2):
            print(threading.current_thread().name+"---"+str(i))
            time.sleep(1)
            cond.notify()
            cond.wait()
if __name__ == "__main__":
    th1 = threading.Thread(target=run1, name="th1")
    th2 = threading.Thread(target=run2, name="th2")
    th1.start()
    th2.start()
    th1.join()
    th2.join()

    print("END")

複製代碼

進程、線程、協程深度理解

進程可在cpu間切換,線程跟着對應的進程走,協程跟着對應的線程走,線程實際上實現了計算機其餘資源(除cpu)的並行使用

複製代碼

網絡編程

tcp

client

# -*- coding:utf-8 -*-
import socket
import threading

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#元組第一個元素爲客戶端要鏈接的服務器的IP地址,第二個參數爲服務器的端口號
client.connect(("10.0.122.158", 8080))

# 建立接收線程
def run1(c):
    while True:
        data = c.recv(1024).decode("utf-8")
        print("服務器說:" + data)
th1 = threading.Thread(target=run1, args=(client,))
th1.start()
def run2(c):
    while True:
        # 456#你真壞
        data = input("請輸入要發送給服務器的消息:")
        data = "talk#" + data
        c.send(data.encode("utf-8"))
th2 = threading.Thread(target=run2, args=(client,))
th2.start()


client.send("register#123#sunck".encode("utf-8"))


th1.join()
th2.join()
複製代碼

server

# -*- coding:utf-8 -*-

import socket
import threading
from person import Person

usersDict = {}

# 一、建立socket
# AF_INET:表示使用IPv4
# SOCK_STREAM:表示TCP協議
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


#二、綁定
# 參數爲一個元組,元組第一個元素爲本機ip,第二元素爲端口號,使用8000以上的值,最大使用到65535
server.bind(("10.0.122.158", 8080))


#三、監聽,設置最多鏈接數
server.listen(50)



def run(clientSocket, clientAddr):
    while True:
        # register#123#sunck
        # talk#456#sunck nice
        data = clientSocket.recv(1024).decode("utf-8")
        #解析數據
        arr = data.split("#")
        if arr[0] == "register":
            per = Person(clientSocket, arr[1], arr[2])
            usersDict[arr[1]] = per
        elif arr[0] == "talk":
            #找到當前用戶的用戶名
            name = None
            for account, per in usersDict.items():
                if per.clientSocket is clientSocket:
                    name = per.name
                    break
            #找到好友
            per = usersDict.get(arr[1])
            friendScoket = per.clientSocket
            # 給好友發送消息
            # sunck說:你真帥
            friendScoket.send((name+":"+arr[2]).encode("utf-8"))


#四、等待客戶端的連接
while True:
    print("等待連接……")
    #客戶端鏈接成功返回客戶端的socket和客戶端的IP地址
    clientSocket, clientAddr = server.accept()
    print(clientAddr, "客戶連接成功")
    #建立線程交互
    th = threading.Thread(target=run, args=(clientSocket, clientAddr))
    th.start()
複製代碼

udp

client

# -*- coding:utf-8 -*-

import socket


client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    data = input("輸入要發送的信息:")
    client.sendto(data.encode("utf-8"), ("10.0.122.158", 8080))





# 如下方式不建議使用
# client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# client.connect(("10.0.122.158", 8081))
# while True:
# data = input("輸入要發送的信息:")
# client.send(data.encode("utf-8"))

複製代碼

server

# -*- coding:utf-8 -*-


# TCP是創建可靠鏈接,而且通訊雙方均可以以流的形式發送數據。相對TCP,UDP則是面向無鏈接的協議

# 使用UDP協議時,不須要創建鏈接,只須要知道對方的IP地址和端口號,就能夠直接發送數據包,可是能不能到達就不知道了

# 雖然UDP傳輸數據不可靠,可是它的優勢是和TCP相比較,速度快,對於不要求可靠到達的數據,能夠使用UDP,廣播類型的軟件常用

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(("10.0.122.158", 8081))

while True:
    data, addr = server.recvfrom(1024)
    print("來自", addr, "的消息:", data.decode("utf-8"))

複製代碼

使用udp冒充飛秋和轟炸

# -*- coding:utf-8 -*-


import socket

info = "1_lbt4_10#32499#002481627512#0#0#0:1289671407:a:b:288:sunck is a good man"

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(info.encode("utf-8"), ("10.0.122.179", 2425))

複製代碼
# -*- coding:utf-8 -*-




import socket

info = "1_lbt4_10#32499#002481627512#0#0#0:1289671407:a:b:288:my name is a GP01 gaolei, you neng nai lai zhao wo!"

for i in range(256):
    ip = "10.%d.%d.%d"%(i,i,i)
    print(ip)

複製代碼

協程

協程概念

# -*- coding:utf-8 -*-

''' 協程:又稱微線程,纖程,是一種用戶態的輕量級線程 發展歷程: 一、最初的生成器變形yield/send 二、引入@asyncio.coroutine和yield from 三、在最近的python3.5版本中引入了async/await關鍵字 理解協程: 一、普通理解:線程是系統級別的,他們是由操做系統調度。協程是程序級別的,由程序員根據需求本身調度。咱們把一個線程中的一個個函數稱爲子程序,那麼子程序在執行的過程當中能夠中斷去執行別的子程序。別的子程序也能夠中斷回來繼續執行以前的子程序,這就是協程。也就是說同一線程下的一段代碼1執行執行着就能夠中斷,而後去執行另外一段代碼2,當再次回來執行代碼塊1的時候,接着從以前中斷的地方開始執行 二、專業理解:協程擁有本身的寄存器上下文和棧,協程在調度切換時,將寄存器上下文和棧保存到其餘的地方,在切回來時,恢復先前保存的寄存器上下文和棧。所以,協程能保留上一次調用時的狀態,每次過程重入時,就至關於進入上一次調用的狀態。 子程序:在全部的語言中都是層級調用,好比A中調用B,B在執行過程當中調用C,C執行完返回,B執行完返回,最後是A執行完畢。是經過棧實現的,一個線程就是執行一個子程序,子程序的調用老是有一個入口,一次返回,調用的順序是明確的 優勢: 一、無需線程上下文切換的開銷,協程避免了無心義的調度,由此提升了性能,可是,程序員必須本身承擔調度的責任,同時協程也失去了標準線程使用多CPU的能力 二、無需原子操做鎖定及同步的開銷 三、方便切換控制流,簡化編程模型 四、高併發+高擴展性+低成本,一個CPU支持上萬個協程不是問題 缺點: 一、沒法利用多核資源,協程的本質是單個線程,它不能同時將單個CPU的多個核使用上,協程須要和進程配合使用才能運行在多CPU上。可是通常不須要,除非是CPU密集型的應用 二、進行阻塞操做(耗時IO)會阻塞整個程序 '''
# def A():
# def B():
# def C():
# pass
# C()
# B()
# A()


def A():
    print(1)
    print(2)
    print(3)
def B():
    print("a")
    print("b")
    print("c")
''' 協程可能實現其餘的打印效果 1 2 a b 3 c '''

複製代碼

協程的數據傳遞

# -*- coding:utf-8 -*-

def func():
    data = "#"
    # yield不但能夠返回一個值,而且它還能夠接收調用者發送的參數
    r = yield data
    print("-------------1", r, data)
    r = yield data
    print("-------------2", r, data)
    r = yield data
    print("-------------3", r, data)
    r = yield data

g = func()
print(g, type(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
#啓動g
print(g.send(None))
print(g.send("a"))
print(g.send("b"))
print(g.send("c"))

複製代碼

協程實現生產者消費者

# -*- coding:utf-8 -*-
import time
import threading

def produce(c):
    print(threading.current_thread().name)
    c.send(None)
    for i in range(5):
        print("[produce] 生成數據%d"%i)
        #發送給消費者
        res = c.send(str(i))
        print("[produce] 消費者反饋:%s"%res)
        time.sleep(2)
    #關閉消費者
    c.close()

def customer():
    print(threading.current_thread().name)
    res = ""
    while True:
        data = yield res
        if not data:
            return
        print("[customer] 消費數據%s"%data)
        res = "200 OK"


c = customer()
produce(c)

複製代碼

同步與異步

# -*- coding:utf-8 -*-

#前言:python因爲GIL(全局鎖)的存在,不能發揮多核的優點,其性能一直被人詬病。然而在IO密集型的網絡編程裏,異步處理比同步處理性能會提高成百上千倍


#同步:只完成事物的邏輯,先執行第一個事物,若是阻塞了,會一直等待,直到這個事物完成,在執行第二個事物,順序執行


#異步:是和同步相對的,指在處理調用這個事物的以後,不會等待這個事物的處理結果,直接去處理第二個事物了,經過狀態、通知、回調來通知調用者處理結果

複製代碼

同步代碼

# -*- coding:utf-8 -*-
import time

def func():
    time.sleep(1)


for i in range(5):
    func()
    print("time:%s"%time.time())

複製代碼

異步代碼

# -*- coding:utf-8 -*-
import time
import asyncio

#定義異步函數(定義一個協程)
async def func():
    #模擬一個耗時IO操做
    asyncio.sleep(1)
    print("time:%s"%time.time())

loop = asyncio.get_event_loop()
for i in range(5):
    loop.run_until_complete(func())

複製代碼

asyncio模塊概述

# -*- coding:utf-8 -*-

''' asyncio模塊使python3.4版本引入的標準庫,直接內置了對異步IO的支持 編程模式:是有一個消息循環,咱們從asyncio模塊中直接獲取一個EventLoop的引用,而後把須要執行的協程扔到EventLoop中執行,就實現了異步 說明:到目前爲止實現協程的不只只有asyncio,還有gevent和tornado都實現了相似的功能 關鍵字說明: 一、evnet_loop 事件循環:程序開啓一個無限循環,把一些函數註冊到事件循環中,當知足條件發生時,調用相應的協程函數 二、coroutine 協程:協程對象,指一個使用async關鍵字定義的函數,它的調用不會當即執行函數,而是會返回一個協程對象。協程對象須要註冊到事件循環中,由事件循環調用 三、task 任務:一個協程對象就是一個原生能夠掛起的函數,任務則是對協程進一步的封裝,其中包含了任務的各類狀態 四、future:表明未來執行或沒有執行的任務的結果,它和task上沒有本質上區別 五、async/await:python3.5用於定義協程的關鍵字,async定義一個協程,await用於掛起阻塞異步調用接口 '''

複製代碼

定義一個協程

# -*- coding:utf-8 -*-

import time
import asyncio

# 經過async關鍵字定義了一個協程,協程不能直接運行,須要將協程加入到事件循環中
async def run(x):
    print("waiting:%d"%x)

start = time.time()

# 獲得一個協程對象,這個時候run()函數沒有執行
coroutine = run(2)
# print(coroutine)

# 建立一個事件循環(注意:真實狀況是在asyncio模塊中獲取一個引用)
loop = asyncio.get_event_loop()
# 將協程對象加入到事件循環
loop.run_until_complete(coroutine)

end = time.time()
print("Time:", end - start)

複製代碼

建立一個task

# -*- coding:utf-8 -*-

import time
import asyncio

async def run(x):
    print("waiting:%d"%x)

start = time.time()





coroutine = run(2)

loop = asyncio.get_event_loop()
# 將協程對象加入到事件循環,協程對象不能直接運行,在註冊事件循環的時候,實際上是run_until_complete方法將協程對象包裝成了一個任務對象,task對象是Future類的子類,保存了協程運行後的狀態,用於將來獲取協程的結果
# loop.run_until_complete(coroutine)

#建立任務
task = asyncio.ensure_future(coroutine)
# task = loop.create_task(coroutine)
print(task)
#將任務加入到事件循環
loop.run_until_complete(task)
print(task)



end = time.time()
print("Time:", end - start)

複製代碼

綁定回調

# -*- coding:utf-8 -*-

import time
import asyncio

async def run(x):
    print("waiting:%d"%x)
    return "done after %ds"%x

#定義一個回調函數,參數爲future,任務對象
def callback(future):
    print("callback:", future.result())

start = time.time()





coroutine = run(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
#給任務添加回調,在任務結束後調用回調函數
task.add_done_callback(callback)
loop.run_until_complete(task)



end = time.time()
print("Time:", end - start)

複製代碼

阻塞和await

# -*- coding:utf-8 -*-

import time
import asyncio

#async能夠定義協程對象,使用await能夠針對耗時的操做進行掛起,就行生成器裏的yield同樣,函數交出控制權。協程遇到await,事件循環將會掛起該協程,執行別的協程,直到其餘協程也掛起或者執行完畢,再進行下一個協程的執行
async def run(x):
    print("waiting:%d" % x)
    # 調用了一個耗時IO操做
    # asyncio.sleep(x)另外一個協程對象
    await asyncio.sleep(x)
    return "done after %ds" % x
def callback(future):
    print("callback:", future.result())

start = time.time()

coroutine = run(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
loop.run_until_complete(task)



end = time.time()
print("Time:", end - start)

複製代碼

併發和並行

# -*- coding:utf-8 -*-

''' 併發:指有多個任務須要同時進行 並行:同一時刻有多個任務執行 併發相似一個老師在同一時間段輔導不一樣的人功課,並行好幾個老師分別同時輔導多個學生。 '''

import time
import asyncio

async def run(x):
    print("waiting:%d" % x)
    # 調用了一個耗時IO操做
    # asyncio.sleep(x)另外一個協程對象
    await asyncio.sleep(x)
    return "done after %ds" % x

start = time.time()

coroutine1 = run(2)
coroutine2 = run(3)
coroutine3 = run(4)
coroutine4 = run(5)

tasks = [
    asyncio.ensure_future(coroutine1),
    asyncio.ensure_future(coroutine2),
    asyncio.ensure_future(coroutine3),
    asyncio.ensure_future(coroutine4)
]


loop = asyncio.get_event_loop()
#一、添加任務列表
# loop.run_until_complete(asyncio.wait(tasks))
#二、
loop.run_until_complete(asyncio.gather(*tasks))

for task in tasks:
    print("Task 返回值:", task.result())



end = time.time()
print("Time:", end - start)

複製代碼

協程嵌套

# -*- coding:utf-8 -*-


import time
import asyncio

async def run(x):
    print("waiting:%d" % x)
    await asyncio.sleep(x)
    return "done after %ds" % x

start = time.time()


async def main():
    coroutine1 = run(2)
    coroutine2 = run(3)
    coroutine3 = run(4)
    coroutine4 = run(5)
    tasks = [
        asyncio.ensure_future(coroutine1),
        asyncio.ensure_future(coroutine2),
        asyncio.ensure_future(coroutine3),
        asyncio.ensure_future(coroutine4)
    ]
    #一、
    # dones, pendings = await asyncio.wait(tasks)
    # for task in dones:
    # print("Task 返回值:", task.result())

    #二、
    # results = await asyncio.gather(*tasks)
    # for result in results:
    # print("task 返回值:", result)


    #三、
    # return await asyncio.wait(tasks)

    #四、
    # return await asyncio.gather(*tasks)

    #五、
    for task in asyncio.as_completed(tasks):
        result = await task
        print("task返回值:", result)

loop = asyncio.get_event_loop()
#一、
# loop.run_until_complete(main())
#二、
# loop.run_until_complete(main())
#三、
# dones, pending = loop.run_until_complete(main())
# for task in dones:
# print("task返回值",task.result())
#四、
# results = loop.run_until_complete(main())
# for result in results:
# print("task 返回值:", result)
#一、
loop.run_until_complete(main())


end = time.time()
print("Time:", end - start)

複製代碼

不一樣線程的事件循環

# -*- coding:utf-8 -*-

#通常狀況咱們的事件循環用於註冊協程,有一些協程須要動態的添加到事件循環中。簡單的方式就是使用多線程,當前線程建立一個事件循環,而後開啓一個新線程,在新線程中啓動事件循環,當前線程不會被block


import asyncio
import time
import threading

def start_loop(lp):
    #啓動事件循環
    asyncio.set_event_loop(lp)
    lp.run_forever()

def run(x):
    print("waiting:%d" % x)
    time.sleep(x)
    print("finish after %ds" % x)

start = time.time()


loop = asyncio.get_event_loop()


#建立新線程,用於啓動事件循環,此時不會阻塞主線程了
threading.Thread(target=start_loop, args=(loop,)).start()

end = time.time()
print("time:", end-start)

#給事件循環添加任務
loop.call_soon_threadsafe(run, 4)
loop.call_soon_threadsafe(run, 6)

複製代碼

新線程協程

# -*- coding:utf-8 -*-

#通常狀況咱們的事件循環用於註冊協程,有一些協程須要動態的添加到事件循環中。簡單的方式就是使用多線程,當前線程建立一個事件循環,而後開啓一個新線程,在新線程中啓動事件循環,當前線程不會被block


import asyncio
import time
import threading

def start_loop(lp):
    #啓動事件循環
    asyncio.set_event_loop(lp)
    lp.run_forever()

async def run(x):
    print("waiting:%d" % x)
    await asyncio.sleep(x)
    print("finish after %ds" % x)

start = time.time()


loop = asyncio.get_event_loop()


#建立新線程,用於啓動事件循環,此時不會阻塞主線程了
threading.Thread(target=start_loop, args=(loop,)).start()

end = time.time()
print("time:", end-start)

#給事件循環添加任務
asyncio.run_coroutine_threadsafe(run(4), loop)
asyncio.run_coroutine_threadsafe(run(6), loop)

複製代碼

獲取網頁信息

# -*- coding:utf-8 -*-

# www.163.com www.baidu.com www.sohu.com www.sina.com.cn www.google.com
# 3 5 2 6

import asyncio
import time
import threading


def start_loop(lp):
    asyncio.set_event_loop(lp)
    lp.run_forever()

async def wget(urlStr):
    print("開始加載%s……"%urlStr)
    connet = asyncio.open_connection(urlStr, 80)
    print("***********************",connet)
    reader, writer = await connet
    #連接成功
    header = "GET / HTTP/1.0\r\nHost: %s\r\n\r\n"%urlStr
    writer.write(header.encode("utf-8"))
    await writer.drain()
    #接收到數據
    while True:
        line = await reader.readline()
        if line == b'\r\n':
            break
        print("%s header--->%s"%(urlStr, line.decode("utf-8").strip()))
    writer.close()


loop = asyncio.get_event_loop()
threading.Thread(target=start_loop, args=(loop,)).start()


#給時間循環添加任務
for url in ["www.163.com","www.sohu.com","www.sina.com.cn","www.baidu.com"]:
    asyncio.run_coroutine_threadsafe(wget(url), loop)
複製代碼

json數據的序列化和反序列化

# 序列化:將Python對象轉換成json字符串
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:將json字符串轉換成Python對象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

# 序列化:將Python對象轉換成json字符串並存儲到文件中
dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:讀取指定文件中的json字符串並轉換成Python對象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

參數說明:
	sort_keys參數: 表示序列化時是否對dict的key進行排序(dict默認是無序的)
	
	indent參數: 表示縮進的意思,它能夠使得數據存儲的格式變得更加優雅、可讀性更強;如	果indent是一個非負整數或字符串,則JSON array元素和object成員將會被以相應的縮進級	   別進行打印輸出;若是indent是0或負數或空字符串,則將只會插入換行,不會有縮進。
    
    separators參數: 儘管indent參數能夠使得數據存儲的格式變得更加優雅、可讀性更強,但	是那是經過添加一些冗餘的空白字符進行填充的。當json被用於網絡數據通訊時,應該儘量	  的減小無用的數據傳輸,這樣能夠節省帶寬並加快數據傳輸速度。json模塊序列化Python對	    象後獲得的json字符串中的','號和':'號分隔符後默認都會附加一個空白字符,咱們能夠經過	 separators參數從新指定分隔符,從而去除無用的空白字符;

    該參數的值應該是一個tuple(item_separator, key_separator)
    若是indent是None,其默認值爲(', ', ': ')
    若是indent不爲None,則默認值爲(',', ': ')
    咱們能夠經過爲separator賦值爲(',', ':')來消除空白字符
    
    ensure_ascii參數: 當該參數的值爲True(默認值)時,輸出中的全部非ASCII字符(好比	   中文)都會被轉義成'\uXXXX'組成的序列,獲得的結果是一個徹底由ASCII字符組成的str實	   例。若是咱們想獲得一我的類可讀的輸出結果,須要把ensure_ascii參數的值設置爲			False。
複製代碼

chardet

# -*- coding:utf-8 -*-



#做用:使用chardet檢測編碼,支持檢測中文、日文、韓文等多種語言

# pip install chardet

import chardet

#數據量小,猜想的不太對
data = "凱".encode("gbk")
print(data)

s = chardet.detect(data)
print(s)
print(type(s))

info = data.decode(s["encoding"])
print(info)

複製代碼

python2和python3的區別

# -*- coding:utf-8 -*-

# 一、性能
#python3.x起始比python2.x效率要低,可是python3.x有極大的優化空間,效率正在追趕,目前已經不差多少。


# 二、編碼
#python3.x原碼文件默認使用utf-8,使變量名更爲廣闊


# 三、語法
# 3.一、去除了<>,改用!=
'''3.二、 / python2.x整型觸發返回整數 python3.x整型觸發返回浮點數,整除使用// '''
# 3.三、加入了nonlocal語句
# 3.四、去除了print語句,加入了print()函數
# print("sunck", end=" ")
# print("kaige")
# 3.五、去除了raw_input語句,加入了input()函數
# 3.六、新的super(),能夠再也不給super()傳遞參數
# class A(object):
# pass
# class B(A):
# def __init__(self):
# super().__int__()
# 3.七、改變了順序操做符的行爲,好比x<y,當x和y類型不匹配時拋出TypeError異常
# 3.八、新式的8進制數字變量



# 四、字符串和字節串
''' python2.x 字符串以8bit字符串存儲 python3.x 字符串以16bit Unicode字符串存儲,如今字符串只有str一種類型 '''




# 五、數據類型
#python3.x去除了long類型,如今只有一種整數類型int,可是它的行爲就像2.x中long
#新增了bytes類型,對應2.x版的八位串







# 六、面向對象
# 引入抽象基類




# 七、異常
#全部異常都從BaseException繼承,並刪除了StardardError
''' python2 try: …… except Exception e: …… python3 try: …… except Exception as e: …… '''





# 八、其餘
# python2.x中的xrange()在python3.x中名爲range()
''' file類被廢棄 python2能夠使用file(path)、open(path) '''
複製代碼

PEP8編碼規範

# -*- coding:utf-8 -*-
#英文教程:https://legacy.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds

#中文教程:https://blog.csdn.net/ratsniper/article/details/78954852



''' 代碼編排 一、縮進4個空格,禁止空格與Tab混用 二、行長79,防止單行的邏輯過於複雜 '''
if 1:
    pass



''' 命名 一、除非在lamdba函數中,不然不要使用單字母的變量名,可是即便在lamdba函數中變量名也要儘量有意義 二、包名、模塊名、函數名所有使用小寫,單詞使用下劃線連接 三、類名、異常名使用首字母大寫的方法,異常名結尾加Error或者Warning 四、全局變量儘可能使用大寫,同一類型的全局變量要加同一的前綴,單詞用下劃線連接 五、自定義的變量、函數名等不要與標準庫名衝突 六、函數名必須有動詞,最好是do_something的句式或者somebody_do_something句式 '''
COLOR_RED = 10
COLOR_BLUE = 11
f = lambda x: x+1
def func(x, y):
    pass
def get_money():
    pass





''' 註釋 一、忌諱沒有註釋和逐行註釋 二、行內註釋 當行邏輯過於複雜添加 三、塊註釋 一段邏輯開始時註釋 四、引入外來算法或者配置時必須在註釋中添加源連接,標明出處 五、函數和類儘可能添加docstring '''
def do_eat(x, y):
    print("------------")




''' 空格 一、:,;後面要跟一個空格,前面沒有空格,行尾分號無需空格 二、二元操做符先後各一個空格 數學運算符、比較運算符、邏輯運算符、位運算符 三、=的注意事項:用於指示關鍵字參數或默認參數值時,不要添加空格 '''
a = 1
def f(x, y=1):
    pass


''' 換行 一、適當添加換行 二、函數間 一、頂級函數空間空2行 二、類的方法空1行 三、文件結尾留空一行 '''



''' import 一、不要使用from xxx import * 二、導入順序(標準庫、第三方、自定義) a、標準庫 b、第三方庫 c、自定義庫 三、單行不要導入多個庫 四、模塊內用不到的不要去import '''



''' 字符串拼接 一、拼接方法 a、字符串相加 (性能最差) b、字符串格式化 c、python3.6支持f操做符 >>> a = 111 >>> b=222 >>> c=333 >>> s = f"{a}-{b}-{c}" >>> s '111-222-333' d、join 二、儘可能使用join方法,由於速度快,內存消耗小 '''




''' 語義 一、要求明確、直白 not x in y x not in y not x is y x is not y '''


''' 測試工具: pep8:即將失效,用pycodestyle替換 pylint:更加嚴格,引入的包沒有使用均可以檢測出來 flake8: '''
複製代碼
相關文章
相關標籤/搜索