Python全棧之路Day22

初次編輯2017年10月28日,星期六 python

摘要

引用:百度數據庫

  1. 列表生成式
  2. 生成器表達式
  3. 面向過程編程
  4. 遞歸

一. 上節課複習

  1. 可迭代的:對象有__iter__方法的都是可迭代的對象
  2. 迭代器:對象 .iter()獲得的結果就是迭代器
  3. 迭代器的特徵:
    1. 迭代器.next()取下一個值
    2. 優勢:
      1. 提供了一種統一的迭代對象的方式,不依賴於索引
      2. 惰性計算
    3. 缺點:
      1. 沒法獲取迭代器的長度
      2. 一次性的,只能日後取值,不能往前退,不能像索引那樣去取得某個位置的值
  4. 生成器:函數帶有yield關鍵字,那麼這個函數的執行結果就是生成器
  5. 生成器的本質就是迭代器
def func():
    n=0
    while True:
        yield n
        n += 1
g=func()
res=next(g)
for i in g:
    pass
  1. 總結yield功能:
    1. 至關於把__iter__和__next__方法封裝到函數內部
    2. 與return相比,return只能返回一次,而yield能夠返回屢次
    3. 函數暫停以及繼續運行的狀態是經過yield保存的
  2. yield的表達式形式:
    food= yield
def eater(name):
    print('%s start to eat '%name)
    while True:
        food=yield
        print('%s eat %s'%(name,food))
e=eater('zhejiangF4')
  1. e.send與next(e)的區別
    1. 若是函數內yield是表達式形式,那麼必須先next(e)
    2. 兩者的共同之處都是可讓函數在上次暫停的位置繼續運行,不同的地方在於send在觸發下一次代碼的執行時,會順便給yield傳一個值
    3. 另 e.send(None) 和next(e) 效果同樣

二. 協程函數初始化裝飾器

  1. 簡單裝飾器
def foo(func):
    def foo1(*args,**kwargs):
        res = func(*args,**kwargs)
        next(res)
        return res        #此處理解 生成器是一次性的
    return foo1

@foo        #eater = foo(eater) = foo1
def eater(name):
    print('%s start to eat food '% name)
    food_list = []
    while True:
        food = yield food_list
        print('%s get %s, to start eat '% (name, food))
        food_list.append(food)
    print('Done')

e = eater('鋼蛋')        #foo1('鋼蛋')
print(e.send('123'))

三. send實現爬網頁

from urllib.request import urlopen

def my_next(func):
    def foo(*args,**kwargs):
        res = func(*args,**kwargs)
        next(res)
        return res
    return foo

@my_next
def get():
    while True:
        url = yield
        res = urlopen(url).read()        #爬網頁返回值
        print(res)        #輸出爬網頁結果

g=get()
g.send('http://www.baidu.com')
g.send('http://www.python.org')

四. 面向過程的程序設計

  1. 面向過程的編程思想:流水線式的編程思想,在程序設計時,須要把整個流程設計出來
    1. 優勢:
      1. 體系結構更加清晰
      2. 簡化程序的複雜度
    2. 缺點:
      1. 可擴展性極其差,因此說面向過程的應用場景是:不須要常常變化的軟件
  2. 實現 #grep -rl 'python' C:\egon
# grep -rl 'python' C:\egon
import os

#裝飾器,將生成器next初始化
def init(func):
    def foo(*args,**kwargs):
        res = func(*args,**kwargs)
        next(res)
        return res
    return foo

@init
def search(target):
    '查找文件絕對路徑'
    while True:
        dir_path = yield        #此yield放在while外仍是內有疑問:yield放在while外就會形成死循環,沒法進行下次yield
        g = os.walk(dir_path)        #g爲迭代器
        for i in g:
            # print(i)
            for j in i[-1]:
                file_path = '%s\\%s'%(i[0],j)
                target.send(file_path)

@init
def opener(target):
    '打開文件獲取文件句柄'
    while True:
        file_path = yield
        with open(file_path) as f:
            target.send((f,file_path))        #send傳遞兩個文件時,需加括號

@init
def cat(target):
    '讀取文件內容'
    while True:
        f,file_path = yield
        for line in f:        #讀取一行文件
            target.send((line,file_path))

@init
def grep(target,pattern):    #傳遞兩個參數,其中pattern爲要過濾的字符串
    '過濾文件一行中是否有python'
    while True:
        line,file_path = yield
        if pattern in line:
            target.send(file_path)        #需傳遞文件路徑

@init
def printer():
    '打印文件路徑'
    while True:
        file_path = yield
        print(file_path)

g=search(opener(cat(grep(printer(),'python'))))
g.send('C:\\egon')

五. 列表生成式

  1. 普通表達
egg_list = []

for i in range(100):
    egg_list.append('egg%s'% i)
print(egg_list)
  1. 列表生成式表達普通
egg_list = ['egg%s'%i for i in range(100)]
print(egg_list)
  1. 列表生成式表達if判斷
#列表內只會添加大於50的數字
egg_list = ['egg%s'%i for i in range(100) if i >50]
print(egg_list)
  1. 語法
[expression for item1 in interable if condition1
                    for item2 in interable if condition2
                    …
                    for itemN in interable if conditionN
                    ]

相似於express

res = []
for item1 in interable:
    if condition1:
        for item2 in interable:
            if condition2:
                …
                for itemN in interable:
                    if conditionN:
                        res.append(expression )
  1. 實現查找文件絕對路徑,以列表的形式表達
import os

g = os.walk('C:\\egon')
l = ['%s\\%s'% (i[0],j) for i in g for j in i[-1]]
print(l)
#['C:\\egon\\a.txt - 副本.txt', 'C:\\egon\\a.txt.txt', 'C:\\egon\\a\\a.txt.txt', 'C:\\egon\\a\\a2.txt.txt', 'C:\\egon\\b\\a.txt.txt', 'C:\\egon\\b\\a1.txt.txt']

六. 三元表達式

name = 'alex'
name = 'egon'

res = 'sb' if name =='alex' else 'shuai'
print(res)        #輸出shuai

七.生成器表達式

  1. 語法:與列表生成式類似
(expression for item1 in interable if condition1
                    for item2 in interable if condition2
                    …
                    for itemN in interable if conditionN
                    )
  1. 優勢:省內存,一次只產生一個值在內存中
  2. 應用:讀取一個大文件的全部內容,而且行處理
#讀取文件,並去掉每一行兩頭空格
f = open('a.txt')
g= (line.strip() for line in f)
print(next(g))

注意:因g爲可迭代的,於是能夠轉換成列表list(g)編程

八. 聲明式編程

  1. 消費總額計算
#雞蛋  5  3
#特斯拉 10000000.2  5
#上衣  1000    3
#褲子  2000    3
#襪子  100
#讀取包含以上信息的文件,並計算總共花費

#第一種傳統寫法
total = []
with open('b.txt','r',encoding='utf-8') as f:
    for line in f:
        goods=line.split()    #split用法及返回值需增強
        # print(goods)
        res = float(goods[1])*float(goods[-1])
        total.append(res)
print(total)
print(sum(total))

#第二種聲明式編程寫法
f=open('b.txt','r',encoding='utf-8')    #不能用with 不然會IO操做報錯
total=(float(line.split()[1])*float(line.split()[-1]) for line in f)

print(total)
print(sum(total))
  1. 文件內容以字典形式嵌套在列表中
#[{'name': '襪子', 'price': '100', 'num': '3'}, {'name': '襪子', 'price': '100', 'num': '3'}, {'name': '襪子', 'price': '100', 'num': '3'}, {'name': '襪子', 'price': '100', 'num': '3'}, {'name': '襪子', 'price': '100', 'num': '3'}]
# 基本寫法
res = []
d = {}

with open('b.txt','r',encoding='utf-8') as f:
    for line in f:
        l = line.split()
        d['name'] = l[0]
        d['price'] = l[1]
        d['num'] = l[2]
        res.append(d)
print(res)
  1. 模擬數據庫查詢
with open('b.txt','r',encoding='utf-8') as f:
    res = (line.split() for line in f)
    dic_g = ({'name':line[0],'price':line[1],'num':line[2]} for line in res)
    goods_dic = next(dic_g)
    print(goods_dic['num'])
  1. 關於with open() 報錯
with open('b.txt') as f:
    d = f
print(d)        #有內存地址,不是很理解
print(next(d))    #報錯

做業

今日總結

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">app

相關文章
相關標籤/搜索