本專題的內容結構:python
unit1:精進的Python語法:編程
(1),上下文管理器:多線程
上下文Conteext:程序執行中的某個狀態app
>程序執行所需的一些內外部參數,構成了程序運行時狀態dom
>上下文是用來表達程序運行狀態的概念,對應內存狀態異步
>上下文是程序中斷保留或恢復運行的重要狀態信息async
上下文管理器:一個能夠在程序中加載獨立上下文的對象異步編程
>萬物皆對象:上下文管理器也是一個對象,管理着一個獨立上下文區域函數
簡單說就是在程序中能夠中止程序,運行程序的對象學習
>上下文管理器使用with 顯示建立
>進入和退出分別對應 __enter__() 和__exit__() 方法
簡單實例:用它來管理文件的操做:
with open("python123.txt",'r') as f:
for line in f:
print(line)
>with結束後,文件被自動關閉
也能夠打開多個文件:
with open("a.txt",'r') as fi,open("b.txt",'w') as fo:
for line in fi:
fo.write(line)
>with 結束後,兩個文件都會被關閉
由於進入(__enter__())時操做的是打開文件,因此離開時,會關閉這個操做
自定義上下文管理器:
class DemoClass:
def __init__(self,name):
self.name= name
def __enter__(self):
print("進入上下文管理器")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文管理器")
def run(self):
print("DemoClass 的某個實例對象在運行")
with DemoClass("python123") as d:
d.run()
輸出:
進入上下文管理器
DemoClass 的某個實例對象在運行
退出上下文管理器
注:如何使用上下文管理器:
>1,with要配合特定對象使用
>2,Python支持:
file,
decimal.Context,
thread.LockType,
threading.Lock,
threading.RLock,
threading.Condition,
threading.Semaphore,
threading.BoundedSempahore
>用戶也可自定義對象
自定義的open類:
class MyOpenClass:
def __init__(self,name,mode):
self.name= name
self.mode= mode
def __enter__(self):
print("進入上下文管理器")
if self.mode == 'r':
self.f = open(self.name,self.mode)
else:
self.f= open(self.name,self.mode)
return self #重點,要將self, 它返回的就是as 後面的那個
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
print("退出上下文管理器")
def read(self):
return self.f.read()
def write(self,s):
self.f.write(s)
with MyOpenClass("d:/test.txt",'r') as f1,MyOpenClass("d:/test02.txt",'w') as f2:
txt = f1.read() #從f1中讀
print(txt)
f2.write(txt) # 寫到f2中去
(2),迭代器類型:
迭代器類型 Iterator Types :實現容器中元素的迭代:
>Container:包含一組元素的數據類型,如 所有組合數據類型
>迭代器:容器之上的一種迭代,迭代方式以對象形式表達
>迭代器定義了逐一獲取容器中元素的方法
迭代器是一個對象,常與for ..in 配合使用,須要重載兩個方法:
>__iter__() 返回迭代器對象自身,配合for ..in 使用時須要
>__next__() 返回容器的下一個元素,若是遍歷結束,產生StopIteration異常
簡言之,迭代器就是一個對象有__iter__() 和__next__() 方法,還有一個異常,
只要是有這兩個方法,還有一個異常,它就是迭代器,它就能夠配合for in 使用
例子:
class DemoIterator:
def __init__(self,container):
self.container = container
self.arg = len(self.container)
def __iter__(self):
return self #必須返回自身,for in 的要求
def __next__(self):
self.arg -=1
if self.arg >=0:
return self.container[self.arg]
else:
raise StopIteration
di = DemoIterator([1,2,3,4,5,6,7,8,9])
for i in di:
print(i,end=',')
輸出:
9,8,7,6,5,4,3,2,1,
迭代器類型 Iterator Types:實現容器中元素的迭代
>迭代器很是經常使用,尤爲是涉及到管理一組數據的應用場景
>自定義類 + for..in 管理一組數據,做爲數據管理的核心自定義數據類型
>迭代器返回下一個元素的方式爲優化程序內存使用提供了重要支持
(3),生成器類型:
生成器 Generator:快速實現迭代器類型的方式:
>生成器是迭代器的另外一個角度詮釋,生成器都是迭代器
>生成器以逐一產生數據爲角度,重點在於迭代邏輯的方便實現
>生成器只須要yield保留字便可定義並表達,不用重載對象方法
生成器函數 Generator Function :實現迭代邏輯的函數:
>生成器函數是生成器的核心,用來實現迭代邏輯
>任何包含yield語句的函數,都是生成器函數
>對於函數來講,yield和return 功能接近,但不徹底相同
例子:
正常的函數:
def getVal():
import random
ls = list(range(10))
print(ls,end=',')
return ls[random.randint(0,9)]
for i in range(10):
print(getVal())
輸出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],5
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],6
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],7
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],4
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],7
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],3
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],6
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],5
注:普通函數:
1,每次調用完整執行後退出
2,若是函數表達了容器概念也如此
形成了計算資源浪費!它每次都從新生成一個列表
生成器解決了這個問題:
例子:
def getVal(max):
import random
ls = list(range(10))
print(ls,end=',')
for _ in range(max):
yield ls[random.randint(0,9)] #每調一次getVal() 就會執行一次,而後停在yield處
for i in getVal(10):
print(i)
輸出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],1
5
7
4
7
5
9
3
7
9
生成器函數的設計原則:
>若想不斷生成數據, 生成器函數須要存在迭代/循環過程
>每次迭代/循環產生的結果以yield方式表達
>生成器函數要與for ..in 配合使用,注意:生成器是一種特殊的迭代器
生成器是特殊的迭代器:也有__next__(),__iter__() ,和stopIteration異常
def getVal(max):
import random
ls = list(range(10))
print(ls,end=',')
print()
for _ in range(max):
yield ls[random.randint(0,9)]
a = getVal(10)
print(a.__next__())
print(a.__next__())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
8
2
(4),裝飾器與語法糖:
裝飾器 Decorator:以函數爲參數實現其額外功能
>需求:對於一個已有函數,如何更新其功能?(同名使用)
>解決方式1: 從新編寫喊,把功能補充進去
>解決方式2:不改變原來函數,增補一個裝飾器給它
緣由是:有的函數是第三方庫中的,有的是長期使用的函數不能隨意修改它,
因此最好的方法是額外增長功能,
以前講過裝飾器:
classmethod() 和staticmethod() 的內置函數(經過裝飾器)
它們參數是函數名
>@classmethod 和 @staticmethod
例子:
<圖>
兩者是等價的
語法糖 Syntactic Sugar :方便使用但無實質功能的語法
>語法糖:一種功能的簡化使用方式,非功能性改變
>Python中採用@做爲語法糖,輔助裝飾器使用
>任何語法糖表達的裝飾器都對應一個函數
並且語法糖能夠迭代使用:
@f2
def func():
pass
它等價於
func = f2(func)
這就是語法糖配合裝飾器使用來簡化 python代碼的過程
簡單說,語法糖不重要,重要的是裝飾器函數:
裝飾器設計原理 :
>語法糖不重要,重要的是裝飾器函數,該函數以函數爲參數
>因爲可能存在裝飾器迭代,每一個裝飾器函數須要返回一個函數引用
>裝飾器內部,進行功能擴展
原始函數:
def func3(a):
print("這是變量{}".format(a))
func3("python123")
如今要對它擴展功能:
def func1(func):
def wrapper(a):
print("我是擴展的")
func(a)
print("我也是擴展的")
return wrapper #必須返回一個函數對象引用,不然沒法利用語法糖
@func1 #等價於 func3 = func1(func3) 因此,func1必定要返回函數引用
def func3(a): #這時的@func1 和def func3(a) 合起來是個新的函數
print("這是變量{}".format(a))
func3("python123")
總結:
def func1(func):
def wrapper(a):
func(a)
print("擴展的")
return wrapper
@func1
def func3(a):
print(a)
func3("heello ") #其實它執行的是wrapper("hello ")
裝飾器的使用場景:
>對原函數功能的補充:測量時間,增長打印
>對原函數功能的調整:利用原函數運行結果,再次運算產生新的結果
>對原函數功能的重寫:只是藉助原來的名字,謹慎修改舊函數
綜合例子:
"mx 爲matrix 矩陣"
def decorator(func):
def wrapper(mx1,mx2,mx1_row,mx1_col,mx2_col):
t1= time.perf_counter()
func(mx1,mx2,mx1_row,mx1_col,mx2_col)
print("{:.5f}".format(time.perf_counter()-t1))
return wrapper
@decorator
def mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col):
rst = [[0 for y in range(mx2_col)] for x in range(mx1_row)]
for i in range(mx1_row): #mx1行
for j in range(mx1_col): # mx1列 mx2行
for k in range(mx2_col): #mx2列
rst[i][k] += mx1[i][j] *mx2[j][k]
return rst
def mxsum(mx,mx_row,mx_col):
s = 0
for i in range(mx_row):
for j in range(mx_col):
s += mx[i][j]
return s
if __name__ =="__main__":
import time
mx1 = [[1,2,3],[7,8,2],[4,2,5]]
mx2 = [[1,2],[9,8],[11,7]]
mx1_row = len(mx1)
mx1_col = len(mx1[0])
mx2_row = len(mx2)
mx2_col = len(mx2[0])
rst = mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col)
sum1 = mxsum(mx1,mx1_row,mx1_col)
sum2 = mxsum(mx2,mx2_row,mx2_col)
print(rst)
print(sum1,sum2)
輸出:
0.00002
None
34 38
咱們的目的是給mxmul計時,可是輸出結果裏卻沒了計算結果:
這時由於咱們的wrapper裏沒有返回計算的結果,(其實被裝飾的函數已經變成了wrapper),
因此要把須要返回的結果返回
修改以下:
"mx 爲matrix 矩陣"
def decorator(func):
def wrapper(mx1,mx2,mx1_row,mx1_col,mx2_col):
t1= time.perf_counter()
ret = func(mx1,mx2,mx1_row,mx1_col,mx2_col)
print("{:.5f}".format(time.perf_counter()-t1))
return ret
return wrapper
@decorator
def mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col):
rst = [[0 for y in range(mx2_col)] for x in range(mx1_row)]
for i in range(mx1_row): #mx1行
for j in range(mx1_col): # mx1列 mx2行
for k in range(mx2_col): #mx2列
rst[i][k] += mx1[i][j] *mx2[j][k]
return rst
def mxsum(mx,mx_row,mx_col):
s = 0
for i in range(mx_row):
for j in range(mx_col):
s += mx[i][j]
return s
if __name__ =="__main__":
import time
mx1 = [[1,2,3],[7,8,2],[4,2,5]]
mx2 = [[1,2],[9,8],[11,7]]
mx1_row = len(mx1)
mx1_col = len(mx1[0])
mx2_row = len(mx2)
mx2_col = len(mx2[0])
rst = mxmul(mx1,mx2,mx1_row,mx1_col,mx2_col)
sum1 = mxsum(mx1,mx1_row,mx1_col)
sum2 = mxsum(mx2,mx2_row,mx2_col)
print(rst)
print(sum1,sum2)
輸出結果:
0.00002
[[52, 39], [101, 92], [77, 59]]
34 38
(5),異步協程函數:
協程Coroutine :在程序層面的多段代碼異步執行:
>Python3.5 新增內置功能:async ,和await保留字
>async: 用於定義異步執行的協程代碼段
>await:異步代碼段之間的手工同步方式
async:
通常能夠對函數,上下文管理器和迭代器使用協程:
async def foo(): 協程函數
pass
async with lock: 協程上下文管理器
pass
async for data in pipeline: 協程迭代器
pass
await:
async def foo(db):
data = await db.fetch("SELECT ...")
pass
獲取異步協程的結果,結果爲awaitalbe對象
await它是在異步的函數中,等待其餘函數返回結果的保留字,
什麼是awaitalbe對象,
咱們一塊兒學習異步協程:
>閱讀:,https://www.python.org/dev/peps/pep-0492/
>理解:理解協程產生的緣由,設計方法及應用理念
>時間:嘗試定義一個協程函數並作初步分析
異步協程主要應用於異步編程,多線程的場景下,
unit2:精進的Python語言:
(1),所有保留字 :
and or not :邏輯運算保留字
as :對象引用保留字,至關於綁定別名
import as 別名(對象引用)
try
except as 對象引用
with ... as 對象應用
assert:
斷言語句保留字,經過異常進行程序輔助調試,
assert 判斷條件
若是條件爲False ,產生AssertionError 異常
例如:
a = 10
try:
assert a<5
except:
print("a太大了")
in :成員關係操做保留字:
• 成員關係提取:for .. in …
• 成員關係判斷:.. in ..
is : 對象判斷保留字 只用來判斷內存是不是同一塊
對象一致性判斷,即比較id()函數結果
之內存對象爲判斷依據:x is y
lambda :
• 定義匿名函數,產生函數對象
• lambda 參數列表: 表達式
yield:
• 定義一個同步或異步(協程)生成器
• yield 表達式
del
• 解除引用與對象的綁定關係,「刪除」引用
• del 引用
True /False:
• True:表示真
• False:表示假,含 0、0.0、[]、{} 、""等
None: 空無保留字
• 表示空無,與False不一樣
• Python最基礎的一個對象
等等...
(2),所有特殊符號
特殊符號:表達Python語法的三種邏輯
• 操做符:表達操做運算
• 分界符:表達式之間的分界
• 特殊含義:具備特殊含義的符號
操做符
+ - * ** / // % @
<< >> & | ^ ~
< > <= >= == !=
• @ 矩陣乘法操做符 還沒有有功能支持 __matmul__(),還沒有支持
分界符
( ) [ ] { }
, : . ; @ = ->
+= -= *= /= //= %= @=
&= |= ^= >>= <<= **=
; 當多行語句在一行表示時,能夠用分號分隔,但不建議
-> 函數註解,輔助對函數參數及返回值類型進行註解
def func(a:int ,b :str) ->str:
return "{} and {} ".format(a,b)
它只是一種註解,一種約定,-> 指的是返回值是str
func(123,"Python")
func("Python",123)
輸出:
123 and Python
Python and 123
Python語法不使用的符號:
$ ? `
(3),所有內置函數 (69)
abs() chr() exec() hex() map() print() staticmethod()
all() classmethod() filter() id() max() property() str()
any() compile() float() input() memoryview() range() sum()
ascii() complex() format() int() min() repr() super()
bin() delattr() frozenset() isinstance() next() reversed() tuple()
bool() dict() getattr() issubclass() object() round() type()
breakpoint() dir() globals() iter() oct() set() vars()
bytearrary() divmod() hasattr() len() open() setattr() zip()
bytes() enumerate() hash() list() ord() slice() __import__()
callable() eval() help() locals() pow() sorted()