python 第五天
第一:
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 匹配任意非空字符
\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 第五天