1. 程式人生 > >python 第五天

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 第五天