標籤:協程函數、模組、包
第一:
1、協程函數:
yield 是把函數的結果作為一個產生器。
一個對象如果有iter和next方法,說明這個對象是一個迭代器、迭代器也是產生器。
如果一個對象只有iter方法,那麼這個對象是一個可迭代的對象。
yield就是把函數的執行結果封裝好iter和next方法、即可得到一個迭代器。
他的功能和return功能類似、都可以傳回值、但是不同的是return只能返回一次值、而yield可以返回多次值。
函數暫停與啟動並執行狀態是又yield儲存。
例1、
#yield
def func(count):
print(‘start‘)
while True:
yield count
count+=1
g=func(10)
print(g)
print(next(g))
print(next(g))
例2:
#yield的運算式應用。
def eater(name):
print(‘%s 說:我開動了‘ %name)
while True:
food=yield
print(‘%s eat %s‘ %(name,food))
res=eater(‘xz‘)
print(next(res))
print(‘================‘)
res1=next(res)
print(res1)
>>
xz 說:我開動了
None
================
xz eat None
Non
#yield的運算式、執行前必須先初始化、或者傳值none
#yield的運算式應用。
def eater(name):
print(‘%s 說:我開動了‘ %name)
while True:
food=yield
print(‘%s 吃 %s‘ %(name,food))
res=eater(‘xz‘)
#第一階段初始化,讓產生器初始到一個位置
next(res)**next的目的就是給yield一個none值
#第二階段、給yield傳值
res.send(‘包子‘)
>>
xz 說:我開動了
xz 吃 包子
xz 吃 骨頭
例3:
#yield的運算式應用。
def eater(name):
print(‘%s 說:我開動了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
res=eater(‘xz‘)
#第一階段初始化,讓產生器初始到一個位置
# next(res)
res.send(None)
#第二階段、給yield傳值
print(res.send(‘包子‘))
print(res.send(‘菜湯‘))
>>
xz 說:我開動了
xz 吃 包子
[‘包子‘]
xz 吃 菜湯
[‘包子‘, ‘菜湯‘]
例4:
#yield的運算式應用。
def eater(name):
print(‘%s 說:我開動了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
def func():
res=eater(‘xiaozhang‘)
next(res)
while True:
food_inp=input(‘>>‘).strip()
if not food_inp:continue
res1=res.send(food_inp)
print(res1)
func()
>>
xiaozhang 說:我開動了
>>菜湯
xiaozhang 吃 菜湯
[‘菜湯‘]
>>
#裝飾器解決初始化的問題:
def init(func):
def warpper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return warpper
@init
def eater(name):
print(‘%s 說:我開動了‘ %name)
food_list=[]
while True:
food=yield food_list
print(‘%s 吃 %s‘ %(name,food))
food_list.append(food)
def func1():
res=eater(‘xiaozhang‘)
while True:
food_inp=input(‘>>‘).strip()
if not food_inp:continue
res1=res.send(food_inp)
print(res1)
func1()
2、面向過程:核心是過程二字、過程即解決問題的步驟。
基於面向過程去設計程式就像一條工業流水線、是一種機械式的思維。
優點:程式結構清晰、易讀、流程化
缺點:可擴充性差、一條流程線只解決一個問題
應用情境:linux核心……、功能單一
例1:使用面向過程的方法、實現grep -lr ‘error‘ /dir/#顯示檔案中有error的列表檔案
import os
def init(func):
def warpper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return warpper
第一階段:找到檔案的決定路徑
@init
def search(target):
while True:
filepath=yield
g=os.walk(filepath)
for pardir,_,files in g:
for file in files:
abspath=r‘%s\%s‘ %(pardir,file)
target.send(abspath)
第二階段:開啟檔案
@init
def opener(target):
while True:
abspath=yield
with open(abspath,‘rb‘) as f:
target.send((abspath,f))
第三階段:迴圈讀
@init
def cat(target):
while True:
abspath,f=yield
for line in f:
res=target.send((abspath,line))
if res:break
第四階段:過濾
@init
def grep(patten,target):
tag=False
while True:
abspath,line=yield tag
tag = False
if patten in line:
target.send(abspath)
tag=True
第五階段:列印該行屬於的檔案名稱
@init
def printer():
while True:
abspath=yield
print(abspath)
g = search(opener(cat(grep(‘error‘.encode(‘utf-8‘), printer()))))
g.send(r‘H:\test‘)
3、遞迴函式:
在一個函數的調用過程中、直接或者間接的調用了函數本身。
遞迴效率比較低。
#直接
def func():
print(‘from func‘)
func()
func()
#間接
def foo():
print(‘from foo‘)
bar()
def bar():
print(‘from bar‘)
foo()
foo()
#遞迴
def age(n):
if n == 1:
return 18
else:
return (age(n-1)+2)
print(age(5))
遞迴必須有一個明確的條件、python沒有偽遞迴
#遞迴
l=[1,3,[11,33],[11,[12,23,[44]]]]
def search(l):
for item in l:
if type(item) is list:
search(item)
else:
print(item)
search(l)
#二分法
l = [1,2,7,7,10,31,44,47,56,99,102,130,240]
#怎麼判斷某一個數字是否在列表內?
def binary_search(l,num):
print(l)
if len(l) > 1:
mid_index=len(l)//2
if num > l[mid_index]:
l=l[mid_index:]
binary_search(l,num)
elif num < l[mid_index]:
l=l[:mid_index]
binary_search(l,num)
else:
print(‘find it‘)
else:
if l[0] == num:
print(‘find it‘)
else:
print(‘not exit‘)
return
binary_search(l,32)
第二、模組與包
1、模組就是包含一個了python定義和聲明的檔案、檔案名稱就是模組名字加上py的尾碼。
2、 模組被匯入預設就是執行模組檔案
3、匯入模組幹了那些事:
A、執行源檔案
B、以原檔案產生一個全域名稱空間
C、在當前位置拿到一個模組名指向2建立的名稱空間
4、from ....import
A、優點:形式上不用使用源檔案內的名字時無需加首碼,使用方便
B、缺點:容易與當前檔案的名稱空間內的名字混淆。
C、橫杠只是對*起作用。有隱藏作用、可以使用__all__=[] 控制*的範圍。
5、模組的載入
A、模組只是在第一次匯入的時候才會執行,之後都是直接引用記憶體中已經載入的。
import sys
print(sys.modules) #存放的是已經載入到記憶體的模組字典
模組的尋找順序:
記憶體中==>內建模組==>sys.path
自訂的模組不能與py內建的模組重名。
一個py檔案有2中用途、指令碼和模組。
py檔案當做指令碼運行時:__name__等於__main__
py檔案當做模組調用時:__name__等於模組名
包就是模組的另一種模式、包下面有一個_init_.py的檔案夾,就是包。
但是在這僅僅是py2.x的定義,在py3.x中沒有_init_.py檔案的檔案夾也是包。
B、無論是import還是from....import匯入、只要遇到點(.)這都是包才有的匯入文法、點的左面一定是一個包。
包即模組、匯入包就是匯入模組。
os模組:
os.path.abspath(__file__)#擷取當前檔案的絕對路徑。
6、日誌模組的參數:
filename:指建立filehandler
filemode:檔案開啟的方式:預設為a可以指定為w
format:值handle使用的日誌顯示格式。
datefmt:指定日期時間格式。
level:設定日誌的層級
stream:用指定的stream建立streamHandler、
日誌的格式:
%(name)s logger的名字、並非使用者名稱
%(levelno)s 數字形式的記錄層級
%(levelnames)s 文本形式的記錄層級
%(pathname)s 調用日誌輸出函數的模組的完整路徑、可能沒有
%(filename)s 調用日誌輸出函數的模組的檔案名稱
%(module)s 調用日誌輸出函數的模組名
%(funcName)s 調用日誌輸出函數的函數名
%(lineno)s 調用日誌輸出函數的語句所在程式碼
%(created)f 目前時間、用UNIX的標準時間的浮點表示
%(relativeCreated)d 輸出日誌資訊時、自logger建立以來的毫秒數
%(asctime)s 字串形式的目前時間、預設格式是"2003-07-08 16:44:22,234"逗號後面的是毫秒
%(thread)d 線程ID、可能咩有
%(threadName)s 線程名、可能無
%(process)d 進程ID、可能無
%(message)s 使用者輸出的訊息
6、python正則:
\w 匹配字母數字下及劃線
\W 匹配非字母數字底線
\s 匹配任意空白字元、等價於[\t\n\r\f]
\S 匹配任意非Null 字元
\d 匹配任一數字、等價於[0-9]
\D 匹配任意非數字
\A 匹配字串開始
\Z 匹配字串的結束、如果是存在換行、只匹配到換行錢的結束字串。
\z 匹配字串結束
\G 匹配最後匹配完成的位置
\n 匹配一個分行符號
\t 匹配一個定位字元
^ 匹配字串的開頭
$ 匹配字串的結尾
. 匹配任一字元、除了分行符號、當re.DOTALL標記被指定時、則可以匹配包括分行符號的任一字元。
[..] 用來表示一組字元、單獨列出[amk]、匹配a或者m或者k
[^..] 不在[]中的字元、[^123] 匹配除了123之外的數字
* 匹配0個或者多個運算式
+ 匹配一次或者多次運算式
? 匹配0次或者1次運算式
{n} 匹配n次運算式
{n,m} 匹配n次到m次運算式
a|b 匹配a或者b
() 匹配括弧內的運算式、也表示一個組。
本文出自 “男兒該自強” 部落格,請務必保留此出處http://nrgzq.blog.51cto.com/11885040/1953216
python 第五天