python基础之协程函数、列表表达式、生成器表达式

一、协程函数

协程函数的定义?
如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数称为协程函数

 

协程函数补充:

def init(func):
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        next(res)
        return res
    return wrapper

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

e = eater('luchuan') #wrapper('luchuan')
# print(e)
# next(e) #e.send(None)

print(e.send('123'))
print(e.send('123'))
print(e.send('123'))
print(e.send('123'))
print(e.send('123'))

 

协程函数的应用?

递归文件夹及子文件夹中的文件,把有'python'参数的文件绝对路径打印出来:

#grep -rl 'python' C:\luchuan

import os,time
def init(func):  #装饰器next()
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        next(res)
        return res
    return wrapper

@init
def search(target):
    '找到文件的绝对路径'
    while True:
        dir_name=yield
        print('车间search开始生产产品:文件的绝对路径')
        time.sleep(0.2)
        g=os.walk(dir_name)
        for i in g:
            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
        print('车间opener开始生产产品:文件句柄')
        time.sleep(0.2)
        with open(file_path) as f:
            target.send((file_path,f))

@init
def cat(target):
    '读取文件内容'
    while True:
        file_path,f=yield
        print('车间cat开始生产产品:文件的一行内容')
        time.sleep(0.2)
        for line in f:
            target.send((file_path,line))

@init
def grep(pattern,target):
    while True:
        file_path,line=yield
        print('车间grep开始生产产品:包含python这一行内容的文件路径')
        time.sleep(0.2)
        if pattern in line:
            target.send(file_path)

@init
def printer():
    while True:
        file_path=yield
        print('车间printer开始生产产品:得到最终的产品')
        time.sleep(0.2)
        print(file_path)

g=search(opener(cat(grep('python',printer()))))
g.send("C:\\luchuan")
# g.send("C:\\lulu") #也可以传其他路径

 

os.walk()方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
在Unix,Windows中有效。

import os

g=os.walk('C:\\luchuan') #遍历所有luchuan路径下的文件绝对路径
for i in g:
    # print(i)
    for j in i[-1]:
        file_path='%s\\%s' %(i[0],j)
        print(file_path)

 

二、面向过程编程

以上协程函数应用就是面向过程编程。

 

面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来。
优点:

  1. 体系结构更加清晰
  2. 简化程序的复杂度

缺点:

  1. 可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件,如:linux内核,httpd,git等软件。

三、列表解析

声明式编程:列表解析、生成器表达式都是声明式编程,就跟声明变量一样。

三元表达式:
三元运算时if-else语句的快捷操作,也被称为条件运算。可以让你的代码更加紧凑,更加美观。

[on_true] if [expression] else [on_false]

x, y = 50, 25
small = x if x < y else y

 

列表解析初识:

egg_list=[]

for i in range(100):  #for循环表示
    egg_list.append('egg%s' %i)
print(egg_list)

l=[ 'egg%s' %i for i in range(100) ]  #列表表达式表示
print(l)

 

复杂的列表解析:

#应用1:
l=[1,2,3,4]
s='hello'

l1=[]
for num in l:
    for s1 in s:
        t=(num,s1)
        l1.append(t)
print(l1)

l1=[ (num,s1) for num in l if num > 2 for s1 in s ]
print(l1)

#应用2:
import os
g=os.walk('C:\\luchuan')
file_path_list=[]

for i in g:
    # print(i)
    for j in i[-1]:
        file_path_list.append('%s\\%s' %(i[0],j))
print(file_path_list)

g=os.walk('C:\\luchuan')
l1=['%s\\%s' %(i[0],j) for i in g for j in i[-1]]
print(l1)

 

四、生成器表达式

把列表解析的[]换成()得到的就是生成器表达式,语法和列表解析一样。

 

生成器表达式初识:

l=['egg%s' %i for i in range(100)]
print(l)

g=l=('egg%s' %i for i in range(1000000000000000000000))
# print(g)
# print(next(g))
# print(next(g))
for i in g:
    print(i)

 

生成器表达式扩展:

# 应用1:
f=open('a.txt')
l=[]
for line in f:
    line=line.strip()
    l.append(line)
print(l)

f.seek(0)
l1=[line.strip() for line in f]
print(l1)

f.seek(0)
g=(line.strip() for line in f)
print(g)
print(next(g))

f=open('a.txt')
g=(line.strip() for line in f)
l=list(g)
print(l)

# 应用2:
nums_g = (i for i in range(3))
print(sum(nums_g))

print(sum([1,2,3,4]))

# 应用3:
money_l=[]
with open('b.txt') as f:
    for line in f:
        goods=line.split()
        res=float(goods[-1])*float(goods[-2])
        money_l.append(res)
print(money_l)

f=open('b.txt')  # 推荐使用这种方式写代码
g=(float(line.split()[-1])*float(line.split()[-2]) for line in f)
print(sum(g))

with open('b.txt') as f:  # 不建议使用这种方式,代码不易观察
    print(sum((float(line.split()[-1])*float(line.split()[-2]) for line in f)))

# 应用4:
res=[]
with open('b.txt') as f:
    for line in f:
        # print(line)
        l=line.split()
        # print(l)
        d={}
        d['name']=l[0]
        d['price']=l[1]
        d['count']=l[2]
        res.append(d)
print(res)

#取出单价>10000
with open('b.txt') as f:
    res=(line.split() for line in f)
    # print(res)
    dic_g=({'name':i[0],'price':i[1],'count':i[2]} for i in res if float(i[1]) > 10000)
    # print(dic_g)
    print(list(dic_g))
                 asdfasdfasdfasdfasdf
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
     123123123123
123123123123

asdfasdfasdfasdf
文件a.txt
apple 10 3
banana 5 10
tesla 1000000.3 1
lenovo 10000 3
文件b.txt

 

总结:

总结:
1、把列表解析的[]换成()得到的就是生成器表达式
2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3、python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如,sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

num=sum(x ** 2 for x in range(4))

而不用多此一举的先构造一个列表:

num=sum([x ** 2 for x in range(4)])

 

练习题:

习题一:

有两个列表,分别存放来老男孩报名学习linux和python课程的学生名字
linux=['钢弹','小壁虎','小虎比','alex','wupeiqi','yuanhao']
python=['dragon','钢弹','zhejiangF4','小虎比']

问题一:得出既报名linux又报名python的学生列表

L=[]
for i in linux:
    for j in python:
        if i == j:
            L.append(i)
print(L)

lp=[i for i in linux for j in python if i==j ]
print(lp)

问题二:得出只报名linux,而没有报名python的学生列表

L=[]
for i in linux:
    if i not in python:
        L.append(i)
print(L)

lp=[i for i in linux if i not in python ]
print(lp)

问题三:得出只报名python,而没有报名linux的学生列表

L = []
for j in python:
    if j not in linux:
        L.append(j)
print(L)

lp=[ j for j in python if j not in linux ]
print(lp)

 

习题二:

shares={
'IBM':36.6,
'lenovo':27.3,
'huawei':40.3,
'oldboy':3.2,
'ocean':20.1
}

问题一:得出股票价格大于30的股票名字列表

L=[]
for i in shares:
    print(i,shares[i])
    if shares[i] > 30:
        L.append(i)
print(L)

lp = [i for i in shares if shares[i] > 30]
print(lp)

问题二:求出所有股票的总价格

L=[]
for i in shares:
    L.append(shares[i])
print(sum(L))

num=sum(shares[i] for i in shares)
print(num)

 

习题三:

l=[10,2,3,4,5,6,7]

得到一个新列表l1,新列表中每个元素是l中对应每个元素值的平方

l1=[]
for i in l:
    l1.append(i**2)
print(l1)

lp=[i**2 for i in l]
print(lp)

过滤出l1中大于40的值,然后求和

l1=[]
for i in l:
    if i**2 > 40:
        l1.append(i**2)
print(sum(l1))

lp=sum(i**2 for i in l if i**2 > 40)
print(lp)

  

 

posted @ 2017-04-12 15:35  luchuangao  阅读(312)  评论(0编辑  收藏  举报