一、装饰器

一、装饰器的知识储备

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

  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. 1、函数可以当做参数传给另外一个函数
  2. 2、一个函数的返回值,也可以是一个函数(打破函数的层级关系)
  3. def f1():
  4. def f2():
  5. print('f2')
  6. return f2 ##打破函数的层级关系
  7. f=f1()
  8. f()

  3、名称空间和作用域

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

二、闭包函数

  1、定义

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

  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()

  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()

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

三、装饰器

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

  1、为何要用装饰器

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

  2、装饰器的定义和原则

  1. 装饰器本身可以是任意可以调用对象,被装饰的对象本身也可以是任意可调用对象
  2. 定义:本质是函数,(装饰其他函数),就是为其他函数添加附加功能
  3.    在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
  4. 原则:1、不能修改被装饰的函数的源代码
  5. 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 %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) #有无返回值,均可处理:有返回值,是相应的返回值,没有返回值是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. 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)) ##查看函数注释信息

显示被装饰对象的注释信息

  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 %s to home' %name)
  44. #有返回值
  45. res=index() #即res=wrapper
  46. print(res)
  47. home('alex')

有参数的装饰器

  1. {"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 wrapper
  15. @timmer
  16. def exec():
  17. print('what are you doing?')
  18. exec()

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

  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()

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

  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')

  四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
注意:从文件中读出字符串形式的字典,可以用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)

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

  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')

  六:编写下载网页内容的函数,要求功能是:用户传入一个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())

  七:为题目五编写装饰器,实现缓存网页内容的功能:
具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为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')

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

  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)

  九 编写日志装饰器,实现功能如:一旦函数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()

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

一、 迭代器

  1、迭代的概念

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

  2、为何要用迭代器?

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

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

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

  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循环会自己处理异常

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

  for循环的工作原理

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

  5、迭代器的优缺点

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

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

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

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

  1. from collections import Iterable
  2. from collections import Iterator
  3.  
  4. #比如给一个字符串
  5. s='abc'
  6. print(isinstance(s,Iterable))#isinstance判断类型的
  7. print(isinstance(s,Iterator))

  判断range函数和map函数

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

二、生成器

  1、生成器的定义

  1. 定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行该函数体代码,会得到一个结果,该结果就是生成器对象
  2. 本质:生成器本质就是迭代器
  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. 1、提供了一种自定义迭代器的方式
  2. 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功能

    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:continue
  17. print(alex_g.send(food))
  18. producer()

多个函数来回切换(传值),下次传值在上次暂停的地点继续

  3、yield from

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

  4、实现: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追加内容

三、面向过程编程

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

  1、定义

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

  2、优缺点

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

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

  3、应用

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

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

  1. [root@iZ94ao17ezcZ ~]# grep -rl 'root' /etc
  2. /etc/passwd
  3. /etc/rc4.d/K30postfix
  4. /etc/rc4.d/K87restorecond
  5. /etc/rc4.d/K85mdmonitor
  6. /etc/rc4.d/S64mysql
  7. /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. @init
  18. def opener(target):
  19. while True:
  20. abs_file_path=yield
  21. with open(abs_file_path,'rb') as f:
  22. target.send((f,abs_file_path))
  23. #第三阶段:循环读出每一行内容
  24. @init
  25. def cat(target):
  26. while True:
  27. f,abs_file_path=yield
  28. for line in f:
  29. res=target.send((line,abs_file_path))
  30. if res:
  31. break
  32. #第四阶段:过滤
  33. @init
  34. def grep(pattern,target):
  35. tag=False
  36. pattern = pattern.encode('utf-8')
  37. while True:
  38. line,abs_file_path=yield tag
  39. tag=False
  40. if pattern in line:
  41. target.send(abs_file_path)
  42. tag=True
  43. #第五阶段:打印该行属于的文件名
  44. @init
  45. def printer():
  46. while True:
  47. abs_file_path=yield
  48. print(abs_file_path)
  49. search(r'G:\data\PyCharm_Project\s19\day4\a',opener(cat(grep('你好',printer()))))

实现方法

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

一、三元表达式

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # __author__ = "wzs"
  4. #2017/9/24
  5.  
  6. # name=input('>>:')
  7. # if name == 'bingbing':
  8. # print('I love you!')
  9. # else:
  10. # print('Goodbye!')
  11.  
  12. name=input('>>:')
  13. #满足条件的返回结果放在最左边,不满足则放在最右边
  14. 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、范例:

  1. g=('egg %s' %i for i in range(10) if i > 3)
  2. # print(g) #生成器
  3. print(next(g)) #取值
  4. 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. ####正确的方式
    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内容如下

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

 a.txt文件内容如下

  1. mouse 100.00 2
  2. computer 4999.00 1
  3. keyboard 300.00 1
  4. mobile 3000.00 2
  5. 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)

列表推导式

闭包、装饰器decorator、迭代器与生成器、面向过程编程、三元表达式、列表解析与生成器表达式的更多相关文章

  1. Python 迭代器-生成器-面向过程编程

    上节课复习:1. 函数的递归调用 在调用一个函数的过程中又直接或者间接地调用了函数本身称之为函数的递归 函数的递归调用有两个明确的阶段: 1. 回溯 一层一层地调用本身 注意: 1.每一次调用问题的规 ...

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

    一.装饰器 一.装饰器的知识储备 1.可变长参数  :*args和**kwargs def index(name,age): print(name,age) def wrapper(*args,**k ...

  3. Python之路【第五篇】: 函数、闭包、装饰器、迭代器、生成器

    目录 函数补充进阶 函数对象 函数的嵌套 名称空间与作用域 闭包函数 函数之装饰器 函数之可迭代对象 函数之迭代器 函数之生成器 面向过程的程序设计思想 一.函数进阶之函数对象 1. 函数对象 秉承着 ...

  4. Python之路第四天,基础(4)-装饰器,迭代器,生成器

    装饰器 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象 ...

  5. Python学习(七) —— 装饰器、迭代器、生成器

    一.装饰器(decorator) 1.装饰器的本质是闭包函数,作用:在不改变函数的调用方式的情况下,给函数的前后添加新的功能 #装饰器的固定结构 def warpper(func): #定义装饰器函数 ...

  6. 周末学习笔记——day02(带参装饰器,wraps修改文档注释,三元表达式,列表字典推导式,迭代器,生成器,枚举对象,递归)

    一,复习 ''' 1.函数的参数:实参与形参 形参:定义函数()中出现的参数 实参:调用函数()中出现的参数 形参拿到实参的值,如果整体赋值(自己改变存放值的地址),实参不会改变,(可变类型)如果修改 ...

  7. Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器)

    Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器) 1.初始函数 2.函数嵌套及作用域 3.装饰器 4.迭代器和生成器 6.内置函数 7.递归函数 8.匿名函数

  8. Python之装饰器、迭代器和生成器

    在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思 ...

  9. Python装饰器、迭代器&生成器、re正则表达式、字符串格式化

    Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用 ...

随机推荐

  1. Vue.js——vue-resource详细介绍

    概述 Vue.js是数据驱动的,这使得我们并不需要直接操作DOM,如果我们不需要使用jQuery的DOM选择器,就没有必要引入jQuery.vue-resource是Vue.js的一款插件,它可以通过 ...

  2. AbpUser 扩展

    AbpUser表存放的信息比较少,现扩展一下信息 1.在Core层添加UserExtend 类,继承 AbpUser<User>,写入以上各项属性字段,并添加Discriminator 字 ...

  3. Android 属性动画监听事件与一个菜单的例子

    简单监听事件 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 3 ...

  4. java知识查漏补缺

    一.重写(override)和重载(overload)的区别 二者除了名字相似,其实没什么联系 范围不同:重载发生在同一个类的不同方法之间.重写发生在父类和子类自荐. 前提: 重载要求:方法名相同,参 ...

  5. JavaWeb之上传与下载

    文件上传概述: 1,文件上传对页面的要求: 必须使用表单,而不能是超链接 表单的method必须是post 表单的enctype必须是multipart/form-data 在表单中添加file表单字 ...

  6. python dict字典添加元素

    已存在的字典进行赋值操作 可为该字典添加新元素例子:a = {‘age’: 23, ‘name’: ‘lala}a[school] = ‘nanhaizhongxue’print a>>& ...

  7. 为Windows编译libobjc2(通过交叉编译的方式)

    前提:Linux系统.git.clang-8.g++-mingw-w64-x86-64.gobjc++-mingw-w64-x86-64. 一.下载源代码 git clone https://gith ...

  8. Singletom 单例

    class Singletom { //最差写法.构造方法是public的,有可能会被new出多个,那就不是单例了. public Singletom(){ } public static Singl ...

  9. 使用bloomfilter

    package bloom; /** * 项目名:SpiderCrawler * 文件名:BloomFilterTest.java * 作者:zhouyh * 时间:2014-8-29 下午02:54 ...

  10. pytest_1安装和启动

    一.安装和启动 1.1 安装pytest 1. 键入Ctrl+R,打开cmd,输入命令至python环境下(本机:D:\Python27>) 2. 在python环境下运行下面的命令即可安装py ...