Day4 闭包装饰器decorator迭代器与生成器面向过程编程三元表达式列表解析与生成器表达式序列化与反序列化

Posted 思维无界限

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day4 闭包装饰器decorator迭代器与生成器面向过程编程三元表达式列表解析与生成器表达式序列化与反序列化相关的知识,希望对你有一定的参考价值。

一、装饰器

一、装饰器的知识储备

  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=1988193190112131
12     func()
13 foo()
View Code

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

技术分享
1 def get(url):
2     return requests.get(url).text
3 # 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 warpper
python_web=index(‘https://www.python.org‘)
print(python_web.__closure__[0])  ##closure 闭包  ##能看到内存地址就不要使用ID

 三、装饰器

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

  1、为何要用装饰器

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

  2、装饰器的定义和原则

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

  添加统计执行时间的功能

技术分享
1 import time
2 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 wrapper
10 
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 to home)
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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None
12         stop=time.time()
13         print(run time is %s %(stop-start))
14         return res ##有无返回值,均可处理
15     return wrapper
16 @timmer #等价于index=timmer(index)  #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名
17 def index():
18     time.sleep(3)
19     print(welcome to index)
20     return 123
21 # 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=wrapper
29 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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None
32             current_user[user] = name ##登录成功记录下来
33             current_user[current_status] == True
34             return res ##有无返回值,均可处理
35         else:
36             print(user or password is wrong)
37     return wrapper
38 @auth #等价于index=timmer(index)  #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名
39 def index():
40     print(welcome to index)
41     return 123
42 # index()
43 
44 @auth #等价于home=timmer(home)
45 def home(name):
46     print(welcome to home)
47 #有返回值
48 res=index()  #即res=wrapper
49 print(res)
有认证功能的装饰器
技术分享
 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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None
22                     current_user[user] = name ##登录成功记录下来
23                     current_user[current_status] = True
24                     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 wrapper
34     return deco
35 @auth(auth_type=mysql)#等价于@deco #index=deco(index)  #index=inner #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名
36 def index():
37     print(welcome to index)
38     return 123
39 # index()
40 
41 @auth(auth_type=file) #等价于home=timmer(home)
42 def home(name):
43     print(welcome to home)
44 #有返回值
45 res=index()  #即res=wrapper
46 print(res)
47 home()
有参数的装饰器
技术分享
 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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None
24                     current_user[user] = name ##登录成功记录下来
25                     current_user[current_status] = True
26                     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 wrapper
36     return deco
37 def timmer(func):
38     # func=index
39     @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 wrapper
46 ##装饰器是有先后顺序的,装饰器装饰的是正下方的函数
47 ##上面装饰器先生效,下面的后生效;但是先执行下面(函数正上方的装饰器)
48 @timmer #index=timmer(wrapper)
49 @auth() # @deco #index=deco(index) #index=wrapper
50 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))  ##查看函数注释信息
显示被装饰对象的注释信息

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

 

  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 wrapper
15 @timmer
16 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 wrapper
15 @timmer
16 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 wrapper
13 @auth
14 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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是None
20             current_user[user] = name ##登录成功记录下来
21             current_user[current_status] == True
22             return res ##有无返回值,均可处理
23         else:
24             print(user or password is wrong)
25     return wrapper
26 @auth #等价于index=timmer(index)  #@装饰器名,会将下面函数名作为参数传给装饰器,然后重新赋值给函数名
27 def index():
28     print(welcome to index)
29     return 123
30 # index()
31 
32 @auth #等价于home=timmer(home)
33 def home(name):
34     print(welcome to home)
35 #有返回值
36 res=index()  #即res=wrapper
37 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 res
15     return wrapper
16 
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] = name
27             user[login_time] = time.time()
28             res = func(*args,**kwargs)
29             return res
30     return wrapper
31 
32 @auth
33 def index():
34     time.sleep(random.randrange(3))
35     print(welcome to index)
36 @auth
37 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).text
10     return wrapper
11 
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):pass
12         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 res
20     return wrapper
21 @make_cache
22 def get(url):
23     return requests.get(url).text
24 
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]=func
11     return deco
12 @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:pass
11         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 wrapper
16     return deco
17 @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=0
3 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、迭代器对象的应用

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循环

二、生成器

  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 start
4         start += step
5 
6 for i in my_range(1,1000000,2):
7     print(i)
使用迭代器,实现range功能

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

  yield的表达式形式应用

技术分享
 1 def eater(name):
 2     food_list=[]
 3     print(%s 开动啦 %name)
 4     while True:
 5         food = yield food_list ##将返回值保存在一个列表中
 6         print(%s 开始吃 %s %(name,food))
 7 
 8 g=eater(alex)
 9 g.send(None) ##相当于next(g)
10 g.send(骨头)  ##next()功能和传值的功能
11 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)
无限传值

实现:tail -f access.log | grep ‘404‘

技术分享tail -f access.log | grep ‘404‘
技术分享
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # __author__ = "wzs"
4 #2017/9/28
5 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的文件,并打印文件绝对路径,命令效果如下

[[email protected] ~]# 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 def search(filepath,target): #找到一个文件路径就往下个阶段传一次
 9     g = os.walk(filepath)
10     for dirname, _, files in g:
11         for file in files:
12             abs_file_path = r%s\%s % (dirname, file)
13             target.send(abs_file_path)
14 @init
15 def opener(target):
16     while True:
17         abs_file_path=yield
18         with open(abs_file_path,rb) as f:
19             target.send((f,abs_file_path))
20 @init
21 def cat(target):
22     while True:
23         f,abs_file_path=yield
24         for line in f:
25             res=target.send((line,abs_file_path))
26             if res:
27                 break
28 @init
29 def grep(pattern,target):
30     tag=False
31     pattern = pattern.encode(utf-8)
32     while True:
33         line,abs_file_path=yield tag
34         tag=False
35         if pattern in line:
36             target.send(abs_file_path)
37             tag=True
38 @init
39 def printer():
40     while True:
41         abs_file_path=yield
42         print(abs_file_path)
43 search(rG:\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 %i
5         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 condition1
2 for item2 in iterable2 if condition2
3 ...
4 for itemN in iterableN if conditionN
5 ]

  相当于

1 res=[]
2 for item1 in iterable1:
3     if condition1:
4         for item2 in iterable2:
5             if condition2
6                 ...
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:因为第一次已将生成器的值取完,再去取,所有结果为0
4     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 2
computer 4999.00 1
keyboard 300.00 1
mobile 3000.00 2
Mac 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)
列表推导式

 



























以上是关于Day4 闭包装饰器decorator迭代器与生成器面向过程编程三元表达式列表解析与生成器表达式序列化与反序列化的主要内容,如果未能解决你的问题,请参考以下文章

day4 迭代器与生成器解析

Python--day4--迭代器-生成器-装饰器-目录

Python 迭代器与生成器及装饰器

装饰器,迭代器与生成器

Day4 装饰器——迭代器——生成器

Day4 - Python基础4 迭代器装饰器软件开发规范