博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Day4 闭包、装饰器decorator、迭代器与生成器、面向过程编程、三元表达式、列表解析与生成器表达式...
阅读量:4636 次
发布时间:2019-06-09

本文共 25443 字,大约阅读时间需要 84 分钟。

一、装饰器

一、装饰器的知识储备

  不想修改函数的调用方式,但是还想在原来的函数前后添加功能

  1、可变长参数  :*args和**kwargs

1 def index(name,age):2     print(name,age)3 4 def wrapper(*args,**kwargs):5     #即args=(1,2,3,4,5),kwargs={'x':1,'y':3}6     index(*args,**kwargs)7     #index(1,2,3,4,5,y=2,x=5)

  2、函数对象:被当做数据传递

1、函数可以当做参数传给另外一个函数    2、一个函数的返回值,也可以是一个函数(打破函数的层级关系)        def f1():            def f2():                print('f2')            return f2  ##打破函数的层级关系        f=f1()        f()

  3、名称空间和作用域

1、名称空间:        分类:分三种            内置名称空间:Python解释器启动则生效,关闭时失效            全局名称空间:执行Python文件时生效            内置名称空间:调用函数时,临时生效;函数调用结束失效         加载顺序:先内置,在全局,最后有可能产生局部         查找名字的顺序:先局部,再全局,最后内置    2、作用域        分类:分两种            全局作用域:全局存活,全局有效            局部作用域:临时存活,局部有效    强调:作用关系在函数定义阶段已经固定,与调用位置无关

二、闭包函数

  1、定义

1、定义在函数内部的函数2、包含对外部作用域名字的引用,而不是对全局作用域名字的引用   那么该内部函数称之为闭包函数

  2、实例

1 x = 1 2 def f1(): 3     x=111111111111 4     def f2():  #f2是闭关函数 5         print(x) 6     return f2  ##获取返回值 7 func=f1() 8 # func() 9 10 def  foo():11     x=198819319011213112     func()13 foo()
View Code

  3、应用:延迟计算/惰性计算(爬网页)

1 def get(url):2     return requests.get(url).text3 # print(get('https://www.toutiao.com/'))4 print(get('https://www.python.org'))
方式一
1 import  requests  #需要pip3 install request 2 def index(url): 3     # url='https://www.python.org' 4     def get(): 5         return requests.get(url).text 6     return get 7 python_web=index('https://www.python.org') 8 baidu_web=index('https://www.baidu.com') 9 python_web()10 baidu_web()
优化

from urllib.request import urlopen

def get(url): #url='http://www.baidu.com'
# url='http://www.baidu.com'
def inner():
return urlopen(url).read()
return inner

baidu=get('http://www.baidu.com')

print(baidu)
res=baidu()
baidu()

def index(url):    # url='https://www.python.org'    def warpper():        return requests.get(url).text    return warpperpython_web=index('https://www.python.org')print(python_web.__closure__[0])  ##closure 闭包  ##能看到内存地址就不要使用ID

 三、装饰器

装饰器就是闭包函数的一种应用场景

  1、为何要用装饰器

开放封闭原则:对修改封闭,对扩展开放

  2、装饰器的定义和原则

装饰器本身可以是任意可以调用对象,被装饰的对象本身也可以是任意可调用对象定义:本质是函数,(装饰其他函数),就是为其他函数添加附加功能   在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。原则:1、不能修改被装饰的函数的源代码         2、不能修改被装饰的函数的调用方式

  添加统计执行时间的功能

1 import time2 def index():3     start=time.time()4     time.sleep(3)5     print('welcome to index')6     stop=time.time()7     print('run time is :[%s}' %(stop-start))8 index()
修改源代码
1 import time 2 def index(): 3     time.sleep(3) 4     print('welcome to index') 5 # index() 6  7 def wrapper(func): 8     start=time.time() 9     func()10     stop=time.time()11     print('run time is %s' %(stop-start))12 #wrapper(index)  ##注意index一定不能加() ,因为使用的是内存地址13 index=wrapper(index)
不修改源代码,修改调用方式

  3、装饰的定义和调用

 使用装饰器添加统计执行时间的功能,不修改原代码,不修改调用方式

1 import time 2 def timmer(func): 3     # func=index 4     def wrapper(): 5         start=time.time() 6         func() 7         stop=time.time() 8         print('run time is [%s]' %(stop-start)) 9     return wrapper10 11 @timmer #等价于index=timmer(index)  #@装饰器名,会将正下方函数名作为参数传给装饰器,然后重新赋值给函数名12 def index():13     time.sleep(3)14     print('welcome to index')15 # index=timmer(index)  ##实践一:重新赋值,然后调用16 # index()17 18 @timmer #等价于home=timmer(home)19 def home():20     time.sleep(3)21     print('welcome %s to home' %name)22 index()23 home()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/9/23 5 ##有参和无参函数都能使用装饰器(*args,**kwargs) 6 import time 7 def timmer(func): 8     # func=index 9     def wrapper(*args,**kwargs):10         start=time.time()11         res=func(*args,**kwargs) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None12         stop=time.time()13         print('run time is %s' %(stop-start))14         return res ##有无返回值,均可处理15     return wrapper16 @timmer #等价于index=timmer(index)  #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名17 def index():18     time.sleep(3)19     print('welcome to index')20     return 12321 # index()22 23 @timmer #等价于home=timmer(home)24 def home(name):25     time.sleep(3)26     print('welcome to home')27 #有返回值28 res=index()  #即res=wrapper29 print(res)30 home('wzs')  #即wrapper('wzs')
被装饰对象有参数,参数类型和数量不固定
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/9/23 5 ##eval 将字符串里面的命令提取出来,执行一下 6 #字符串转成字典 7 # dic='{"name":"alex","password":"alex123"}' 8 # d=eval(dic) 9 # print(type(d))10 11 ##从文件取用户信息进行认证12 # with open('db.txt',encoding='utf-8') as f:13 #     data=f.read()14 #     dic=eval(data)15 #     print(dic['name'])16 17 ##保存用户登录状态18 current_user={
'user':None,'current_status':False}19 def auth(func):20 def wrapper(*args,**kwargs):21 if current_user['user'] and current_user['current_status']:22 return func(*args,**kwargs)23 name=input('please input your name:').strip()24 password=input('please input your password:').strip()25 26 ##用户的认证来源有多种:文件,数据库等等27 with open('db.txt', encoding='utf-8') as f:28 user_dic = eval(f.read())29 # if name == user_dic['name'] and password == user_dic['password']:30 if name in user_dic and password == user_dic[name]:31 res=func(*args,**kwargs) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None32 current_user['user'] = name ##登录成功记录下来33 current_user['current_status'] == True34 return res ##有无返回值,均可处理35 else:36 print('user or password is wrong')37 return wrapper38 @auth #等价于index=timmer(index) #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名39 def index():40 print('welcome to index')41 return 12342 # index()43 44 @auth #等价于home=timmer(home)45 def home(name):46 print('welcome to home')47 #有返回值48 res=index() #即res=wrapper49 print(res)
有认证功能的装饰
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/9/23 5 ####使用装饰器 6 import time 7 from functools import wraps  ##引用Python自带的装饰器 8 current_user={
'user':None,'current_status':False} 9 def auth(auth_type='file'):10 def deco(func):11 def wrapper(*args,**kwargs):12 if auth_type == 'file':13 if current_user['user']:14 return func(*args,**kwargs)15 name=input('please input your name:').strip()16 password=input('please input your password:').strip()17 18 ##用户的认证来源有多种:文件,数据库等等19 with open('db.txt', encoding='utf-8') as f:20 user_dic = eval(f.read())21 # if name == user_dic['name'] and password == user_dic['password']:22 if name in user_dic and password == user_dic[name]:23 res=func(*args,**kwargs) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None24 current_user['user'] = name ##登录成功记录下来25 current_user['current_status'] = True26 return res ##有无返回值,均可处理27 else:28 print('user or password is wrong')29 elif auth_type == "mysql":30 print('mysql')31 elif auth_type == 'ldap':32 print('ldap')33 else:34 print('not valid auth_type')35 return wrapper36 return deco37 def timmer(func):38 # func=index39 @wraps(func) ##利用Python的自带的装饰器(可以查到注释信息)40 def wrapper():41 start=time.time()42 func()43 stop=time.time()44 print('run time is %s' %(stop-start))45 return wrapper46 ##装饰器是有先后顺序的,装饰器装饰的是正下方的函数47 ##上面装饰器先生效,下面的后生效;但是先执行下面(函数正上方的装饰器)48 @timmer #index=timmer(wrapper)49 @auth() # @deco #index=deco(index) #index=wrapper50 def index():51 '''这是函数'''52 time.sleep(3)53 print('welcome to index')54 # index()55 56 @timmer #等价于home=timmer(home)57 @auth()58 def home():59 time.sleep(3)60 print('welcome to home')61 # index()62 # home()63 print(index.__doc__) ##加上装饰器后默认是返回None ;调用系统自带的装饰器from functools import wraps ,引用@wraps后,可以查看函数的注释信息64 # print(help(index)) ##查看函数注释信息
显示被装饰对象的注释信息
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/9/23 5  6 current_user={
'user':None,'current_status':False} 7 def auth(auth_type='file'): ##给装饰器传参数,最多三层(已经满足所有需求,一般情况下,直接调用别人的有参装饰器) 8 def deco(func): 9 def wrapper(*args,**kwargs):10 if auth_type == 'file':11 if current_user['user']:12 return func(*args,**kwargs)13 name=input('please input your name:').strip()14 password=input('please input your password:').strip()15 16 ##用户的认证来源有多种:文件,数据库等等17 with open('db.txt', encoding='utf-8') as f:18 user_dic = eval(f.read())19 # if name == user_dic['name'] and password == user_dic['password']:20 if name in user_dic and password == user_dic[name]:21 res=func(*args,**kwargs) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None22 current_user['user'] = name ##登录成功记录下来23 current_user['current_status'] = True24 return res ##有无返回值,均可处理25 else:26 print('user or password is wrong')27 elif auth_type == "mysql":28 print('mysql')29 elif auth_type == 'ldap':30 print('ldap')31 else:32 print('not valid auth_type')33 return wrapper34 return deco35 @auth(auth_type='mysql')#等价于@deco #index=deco(index) #index=inner #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名36 def index():37 print('welcome to index')38 return 12339 # index()40 41 @auth(auth_type='file') #等价于home=timmer(home)42 def home(name):43 print('welcome %s to home' %name)44 #有返回值45 res=index() #即res=wrapper46 print(res)47 home('alex')
有参数的装饰器
{
"alex":"alex123","egon":"egon123","wzs":"wzs123"}
db.txt

  装饰器最多三层函数,三层几乎满足所有的需求了

  4、练习题

  一:编写函数,(函数执行的时间是随机的)

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import time 7 def timmer(func): 8     def wrapper(*args,**kwargs): 9         start = time.time()10         func(*args,**kwargs)11         stop = time.time()12         print('execution time is %s' %(start))13 14     return wrapper15 @timmer16 def exec():17     print('what are you doing?')18 exec()
View Code

  二:编写装饰器,为函数加上统计时间的功能

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import time 7 def timmer(func): 8     def wrapper(*args,**kwargs): 9         start = time.time()10         func(*args,**kwargs)11         stop = time.time()12         print('execution time is %s' %(start))13 14     return wrapper15 @timmer16 def exec():17     print('what are you doing?')18 exec()
View Code

  三:编写装饰器,为函数加上认证的功能

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 def auth(func): 7     def wrapper(*args,**kwargs): 8         name = input('please your name>>:').strip() 9         password = input('please your password>>:').strip()10         if name == 'wzs' and password == 'wzs123':11             func(*args,**kwargs)12     return wrapper13 @auth14 def login(name):15     print('%s 欢迎登录' %(name))16 login('wzs')
View Code

  四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 current_user={
'user':None,'current_status':False} 7 def auth(func): 8 def wrapper(*args,**kwargs): 9 if current_user['user'] and current_user['current_status']:10 return func(*args,**kwargs)11 name=input('please input your name:').strip()12 password=input('please input your password:').strip()13 14 ##用户的认证来源有多种:文件,数据库等等15 with open('db.txt', encoding='utf-8') as f:16 user_dic = eval(f.read())17 # if name == user_dic['name'] and password == user_dic['password']:18 if name in user_dic and password == user_dic[name]:19 res=func(*args,**kwargs) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None20 current_user['user'] = name ##登录成功记录下来21 current_user['current_status'] == True22 return res ##有无返回值,均可处理23 else:24 print('user or password is wrong')25 return wrapper26 @auth #等价于index=timmer(index) #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名27 def index():28 print('welcome to index')29 return 12330 # index()31 32 @auth #等价于home=timmer(home)33 def home(name):34 print('welcome to home')35 #有返回值36 res=index() #即res=wrapper37 print(res)
View Code

  五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import time,random 7 user={
'user':None,'login_time':None,'timeout':0.000005,} 8 def timmer(func): 9 def wrapper(*args,**kwargs):10 exe_start = time.time()11 res = func(*args,**kwargs)12 exe_stop = time.time()13 print('%s' %(exe_stop - exe_start))14 return res15 return wrapper16 17 def auth(func):18 def wrapper(*args,**kwargs):19 if user['user']:20 timeout = time.time() - user['login_time']21 if timeout < user['timeout']:22 return func(*args,**kwargs)23 name = input('your name>>:').strip()24 password = input('your password>>:').strip()25 if name == 'wzs' and password == 'wzs123':26 user['user'] = name27 user['login_time'] = time.time()28 res = func(*args,**kwargs)29 return res30 return wrapper31 32 @auth33 def index():34 time.sleep(random.randrange(3))35 print('welcome to index')36 @auth37 def home(name):38 time.sleep(random.randrange(3))39 print('welcome %s to home' %name)40 41 index()42 home('wzs')
View Code

  六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import requests 7 def index(url): 8     def wrapper(): 9         return requests.get(url).text10     return wrapper11 12 index_web = index('https://www.python.org')13 print(index_web())
View Code

  七:为题目五编写装饰器,实现缓存网页内容的功能:

具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import requests,os 7 cache_file = 'cache.txt' 8 def make_cache(func): 9     def wrapper(*args,**kwargs):10         if not os.path.exists(cache_file):11             with open(cache_file,'w'):pass12         if os.path.getsize(cache_file):13             with open(cache_file,'r',encoding='utf-8') as f:14                 res = f.read()15         else:16             res = func(*args,**kwargs)17             with open(cache_file,'w',encoding='utf-8') as f:18                 f.write(res)19         return res20     return wrapper21 @make_cache22 def get(url):23     return requests.get(url).text24 25 get('https://www.python.org')
View Code

  八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 route_dic={} 7  8 def make_route(name): 9     def deco(func):10         route_dic[name]=func11     return deco12 @make_route('select')13 def func1():14     print('select')15 16 @make_route('insert')17 def func2():18     print('insert')19 20 @make_route('update')21 def func3():22     print('update')23 24 @make_route('delete')25 def func4():26     print('delete')27 28 print(route_dic)
View Code

  九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定

注意:时间格式的获取
import time
time.strftime('%Y-%m-%d %X')

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # __author__ = "wzs" 4 #2017/10/7 5  6 import time,os 7 def auth(logfile): 8     def deco(func): 9         if not os.path.exists(logfile):10             with open(logfile,'w',encoding='utf-8') as f:pass11         def wrapper(*args,**kwargs):12             res = func(*args,**kwargs)13             with open(logfile,'a',encoding='utf-8') as f:14                 f.write('%s %s run'%(time.strftime('%Y-%m-%d %X'),func.__name__))15         return wrapper16     return deco17 @auth('access.log')18 def index():19     print('this is my index')20 21 index()
View Code

二、迭代器、生成器、面向过程

  一、 迭代器

  1、迭代的概念

迭代:迭代是个重复的过程,每次重复都是基于上一次的结果来的(软件版本的迭代)

  2、为何要用迭代器?

1 l=['a','b','c']2 n=03 while n < len(l):4     print(len(n))5     n += 1
对于序列类型,如字符串,列表,元组,可以使用基于索引的迭代取值方式 对于没有索引的类型,如字典、集合、文件,这种方式不再适用,于是我们必须找出一种不依赖于索引的取值方式,这就是迭代器找找

  3、什么是可迭代对象?什么是迭代器对象?

可迭代对象:只要对象内置有__iter__方法,obj.__iter__ 例如:字符串,列表,元组,字典,集合
1 'hello'.__iter__()2 [1,2].__iter__()3 (1,2).__iter__()4 {
'a':1}.__iter__()5 {1,2,3}.__iter__()
迭代器对象:对象既有内置有__iter__方法,又内置有__next__,如文件对象   可迭代对象通过.__iter__方法,得到的结果就是迭代器对象 文件既是可迭代对象,又是迭代器对象 例如:文件
1 open('a.txt','w').__iter__()2 open('a.txt','w').__next__()
注意:迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象

  4、迭代器对象的应用 

  next(iter_dic)这个方法和iter_dic.__next__()方法一样,推荐用next(iter_dic)这个

1 dic={
'name':'alex','age':29,'sex':'male'}2 iter_dic=dic.__iter__()3 print(iter_dic.__next__())4 print(iter_dic.__next__())5 print(iter_dic.__next__()) ##等价于print(next(iter_dic))6 # print(iter_dic.__next__()) ##当没有值了,继续取值会报错

  有了迭代器对象取值,所有类型的数据都可以使用(不依赖索引取值)

1 dic={
'name':'alex','age':29,'sex':'male'}2 iter_dic=dic.__iter__()3 while True: ###可以使用try ....except....使用手工捕捉异常,避免程序崩溃4 try:5 k=next(iter_dic)6 print(dic[k])7 except StopIteration:8 break

  使用for循环,for循环会自己处理异常

#相当于iter_dic=dic.iter__()for k in dic:    print(dic[k])

  for循环的工作原理

for 循环的工作原理    1、执行in后对象的dic.__iter__()方法    2、执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码    3、重复过程2,知道捕捉到异常StopIteration

  5、迭代器的优缺点

优点:         1、提供一种统一的迭代取值方式,该方式不再依赖于索引         2、更节省内存     缺点:         1、无法统计长度         2、一次性的,只能往后走,不能往前退,无法获取指定位置的值   应用场景:       for循环

  6、判断可迭代对象和迭代器的方法

    1、方法一:判断内部是不是实现了__next__方法
'__iter__' in dir(str)#如果__iter__在这个方法里面,就是可迭代的
    2、方法二:

    Iterable 判断是不是可迭代对象;Iterator 判断是不是迭代器

from collections import Iterable  from collections import Iterator#比如给一个字符串s='abc'print(isinstance(s,Iterable))#isinstance判断类型的print(isinstance(s,Iterator))

  判断range函数和map函数

map1=map(abs,[1,-2,3,-4])print(isinstance(map1,Iterable))print(isinstance(map1,Iterator))#map方法自带迭代器s=range(100)#是一个可迭代的,但是不是迭代器print(isinstance(s,Iterable))print(isinstance(s,Iterator))

  二、生成器

  1、生成器的定义

定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行该函数体代码,会得到一个结果,该结果就是生成器对象本质:生成器本质就是迭代器
1 def fun(): 2     print('first') 3     yield 1,2,3 4     print('second') 5     yield 2 6     print('third') 7     yield 3 8  9 g=fun()10 # print(next(g))11 for i in g:12     print(i)
范例:yield

  2、yield的功能

1、提供了一种自定义迭代器的方式    2、对比return,可以返回多次之,挂起函数的运行状态

  自定义功能,可以生成无穷多个值,因为同一时间在内部中只有一个值(节约资源)

1 def my_range(start,stop,step=1):2     while start < stop:3         yield start4         start += step5 6 for i in my_range(1,1000000,2):7     print(i)
使用迭代器,实现range功能
    1、send功能:

  1、初始化(None),和next效果一样;2、传值

    2、yield的表达式形式应用
1 def eater(name): 2     food_list=[] 3     print('%s 开动啦' %name) 4     while True: 5         food = yield food_list ##将返回值保存在一个列表中 6         food_list.append(food) 7         print('%s 开始吃 %s' %(name,food)) 8  9 g=eater('alex')10 g.send(None) ##相当于next(g)11 g.send('骨头')  ##next()功能和传值的功能12 g.send('包子')  ##可以多次传值13 print(g.send("饺子"))  ###打印返回值
send应用
1 def f1(): 2     while True: 3         x=yield 4         print(x) 5 g=f1() 6 next(g) #初始化 7 g.send(12) 8 g.send(12) 9 g.send(12)10 # g.close()  ##只能传值到这个位置,在执行下面的传值,就报错11 g.send(12)12 g.send(12)
无限传值
1 def eater(name): 2     print('%s 说:我开动啦' %name) 3     food_list = [] 4     while True: 5         food = yield food_list 6         food_list.append(food) 7         print('%s eat %s' %(name,food)) 8  9 def producer():10     alex_g = eater('alex')11     #第一阶段:初始化12     next(alex_g)13     #第二阶段:14     while True:15         food = input('>>:').strip()16         if not food:continue17         print(alex_g.send(food))18 producer()
多个函数来回切换(传值),下次传值在上次暂停的地点继续

  3、yield from

def func():    # for i in 'AB':    #     yield i    yield from 'AB' #AB就相当于上面的for循环,把循环简化了    # yield from [1,2,3]g = func()# print(g)  #生成器print(list(g))

  4、实现:tail -f access.log | grep '404'

tail -f access.log | grep '404'
1 #!/usr/bin/env python2 # -*- coding:utf-8 -*-3 # __author__ = "wzs"4 #2017/9/285 with open('access.log','a') as f:6     f.write('pythonxxx19xxxxJHHH404GG\n')
向access.log追加内容

  三、面向过程编程

面向过程绝对不是函数编程那么简单,对象过程是一种变成思路、思想,而变成思路是不依赖于具体语言的或语法的。
核心是过程二字,过程即解决问题的步骤,基于面向过程去设计程序就像在设计一条工业流水线,是一种机械式的思维方式
r是后面的特殊符号转换字符串

  1、定义

面向过程的核心是过程,过程指的是解决问题的步骤:即先干什么再干什么。

  2、优缺点

优点:复杂的问题流程化,进行简单化

缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

  3、应用

扩展性要求不高的场景,典型案例例如:Linux内核,git,httpd(程序实现的流程图)

  4、范例:实现grep -rl 'root' /etc的效果,从/etc开始递归抓取文件中含有root的文件,并打印文件绝对路径,命令效果如下

[root@iZ94ao17ezcZ ~]# grep -rl 'root' /etc/etc/passwd/etc/rc4.d/K30postfix/etc/rc4.d/K87restorecond/etc/rc4.d/K85mdmonitor/etc/rc4.d/S64mysql/etc/rc4.d/K92ip6tables
1 import os 2 def init(func): 3     def inner(*args,**kwargs): 4         g=func(*args,**kwargs) 5         next(g) 6         return g 7     return inner 8 #第一阶段:找到所有文件的绝对路径 9 def search(filepath,target): #找到一个文件路径就往下个阶段传一次10     g = os.walk(filepath)    #得到文件路径的生成器11     for dirname, _, files in g:  #拼接出想要文件的绝对路径12         for file in files:13             abs_file_path = r'%s\%s' % (dirname, file)14             target.send(abs_file_path)15 16 #第二阶段:打开文件17 @init18 def opener(target):19     while True:20         abs_file_path=yield21         with open(abs_file_path,'rb') as f:22             target.send((f,abs_file_path))23 #第三阶段:循环读出每一行内容24 @init25 def cat(target):26     while True:27         f,abs_file_path=yield28         for line in f:29             res=target.send((line,abs_file_path))30             if res:31                 break32 #第四阶段:过滤33 @init34 def grep(pattern,target):35     tag=False36     pattern = pattern.encode('utf-8')37     while True:38         line,abs_file_path=yield tag39         tag=False40         if pattern in line:41             target.send(abs_file_path)42             tag=True43 #第五阶段:打印该行属于的文件名44 @init45 def printer():46     while True:47         abs_file_path=yield48         print(abs_file_path)49 search(r'G:\data\PyCharm_Project\s19\day4\a',opener(cat(grep('你好',printer()))))
实现方法

三、三元表达式、列表解析、生成器表达式

  一、三元表达式

#!/usr/bin/env python# -*- coding:utf-8 -*-# __author__ = "wzs"#2017/9/24# name=input('>>:')# if name == 'bingbing':#     print('I love you!')# else:#     print('Goodbye!')name=input('>>:')#满足条件的返回结果放在最左边,不满足则放在最右边print('I love you' if name == 'wzs' else 'Goodbye')

  二、列表解析(列表推倒式)

   1、范例:当产egg的数量大于3时,将超过3的部分放入仓库中

1 egg_list=[]2 for i in range(10):3     if i > 3:4         res='egg %s' %i5         egg_list.append(res)6 7 print(egg_list)
常规写法
1 l=['egg%s' %i for i in range(10) if i > 3]2 print(l)
列表推倒式

  2、语法

1 [expression for item1 in iterable1 if condition12 for item2 in iterable2 if condition23 ...4 for itemN in iterableN if conditionN5 ]

  相当于

1 res=[]2 for item1 in iterable1:3     if condition1:4         for item2 in iterable2:5             if condition26                 ...7                 for itemN in iterableN:8                     if conditionN:9                         res.append(expression)

  3、优点:方便,改变了编程习惯,可称之为声明式编程

  三、生成器表达式

  1、语法

  将列表推导式的[ ]换成( ),就是生成器表达式

  2、范例:

g=('egg %s' %i for i in range(10) if i > 3)# print(g) #生成器print(next(g)) #取值print(list(g)) #生成器是迭代器对象 因而可以转成列表  输出列表中的元素

  3、优点:省内存,一次在内存中只产生一个值

  四、声明式编程练习题

  1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变成大写

1 names=['egon','alex_sb','wupeiqi','yuanhao']2 names=[name.upper() for name in names]3 print(names)
列表推导式

  2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度

1 names=['egon','alex_sb','wupeiqi','yuanhao']2 names=[len(name) for name in names if not name.endswith('sb')]3 print(names)
列表推导式

  3、求文件test中最长的行的长度(长度按字符个数算,需要使用max函数)

  读取文件的每一行内容,然后计算出每行字符的数量,最后使用max函数取出最长一行字符的数量

1 with open('test',encoding='utf-8') as f:2     print(max(len(line) for line in f))
生成器表达式

  4、求文件test中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

  每次必须重新打开文件或seek到文件开头,因为迭代完一次就结束了

1 with open('test',encoding='utf-8') as f:2     print(sum(len(line) for line in f)) #第一次计算出所有行总的字符串3     print(sum(len(line) for line in f)) #得出的结果是0:因为第一次已将生成器的值取完,再去取,所有结果为04     print(sum(len(line) for line in f))
生成器表达式

  5、思考题

1 with open('a.txt') as f:2     g=(len(line) for line in f)3 print(sum(g)) #为何报错?
####正确的方式 1 with open('test') as f:2     # g=(sum(len(line) for line in f))3     g=(len(line) for line in f)4     print(sum(g))

  6、文件shopping.txt内容如下

求总共花了多少钱?打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]求单价大于10000的商品信息,格式同上

 a.txt文件内容如下

mouse 100.00 2computer 4999.00 1keyboard 300.00 1mobile 3000.00 2Mac 12000 1

  1问:sum

1 with open('a.txt',encoding='utf-8') as f:2     info=[line.split() for line in f]3     cost=sum(float(unit_price)*int(count) for _,unit_price,count in info)4     print(cost)
1问 总花费

  2问:打印出所有商品的信息

1 with open('a.txt',encoding='utf-8') as f:2     info=[{3         'name':line.split()[0],4         'price':line.split()[1],5         'count':line.split()[2],6     } for line in f]7     print(info)
列表推导式

  3问:打印单价大于10000的商品信息

1 with open('a.txt',encoding='utf-8') as f:2     info=[{3         'name':line.split()[0],4         'price':line.split()[1],5         'count':line.split()[2],6     } for line in f if float(line.split()[1]) > 10000]7     print(info)
列表推导式

转载于:https://www.cnblogs.com/happy-king/p/7589328.html

你可能感兴趣的文章
MyEclipse安装Freemarker插件
查看>>
计算多项式的值
查看>>
DP(动态规划)
查看>>
chkconfig
查看>>
TMS320F28335项目开发记录2_CCS与JTAG仿真器连接问题汇总
查看>>
最强的篮球队和马尔可夫模型
查看>>
hdu-4302-Holedox Eating-线段树-单点更新,有策略的单点查询
查看>>
cocos2d-x 音效中断问题
查看>>
设计模式简要笔记
查看>>
子分类账知识学习(汇总网上比较有用的资料)
查看>>
pyQt 每日一练习 -- 登录框
查看>>
wp 删除独立存储空间文件(多级非空文件夹删除)
查看>>
Loadrunner安装使用入门
查看>>
smartupload 上传文件时 把页面编码改成gbk 解决乱码
查看>>
EPS是什么格式
查看>>
input禁止显示历史输入记录
查看>>
Python的数据库操作(Sqlalchemy)
查看>>
2.抽取代码(BaseActivity)
查看>>
My simplified pickit2 clone
查看>>
Redis 入门知识
查看>>