一、装饰器

  1.1 闭包函数用法

  1. # 需求:
  2. # 执行一个函数前需要认证是否登录,如果登录则不需再登录.
  3. # 只认证一次,后续操作无需认证
  4. # 要求认证使用闭包函数用法
  5. # 闭包函数 = 函数嵌套 + 命名空间作用域 + 函数对象
  1. login_status = {
  2. 'user':None,
  3. 'status':None
  4. }
  5.  
  6. def login(user:str,pwd:str):
  7. if user == 'jmz' and pwd =='':
  8. return True
  9. else:
  10. return False
  11.  
  12. # 认证用户是否登录成功
  13. def auth(func):
  14. def wrapper(*args,**kwargs):
  15. if login_status['user'] and login_status['status']:
  16. return func(*args,**kwargs)
  17. else:
  18. uname = input('username>>').strip()
  19. upwd = input('password>>').strip()
  20. res =login(uname,upwd)
  21. if res:
  22. return func(*args, **kwargs)
  23. else:
  24. print('认证失败')
  25. return wrapper
  26.  
  27. def index():
  28. print('from index')
  29.  
  30. index = auth(index)
  31.  
  32. def cat():
  33. print('form cat')
  34.  
  35. index()
  36. cat()

实现

  1.2 什么是装饰器

  1. # 什么是装饰器
  2. # 1、装饰即修饰,器指的就是工具
  3. # 2、装饰器本身可以是任意可调用的对象
  4. # 3、被装饰的对象也可以是任意可调用的对象

  1.3 为什么要使用装饰器

  1. # 为什么要使用装饰器
  2. # 1、在不改变原有的调用方式,不改变原方法的前提下,如何实现对内容上的新增??
  3. # 例如:
  4. # 今天公司cto要求对一些方法添加文件的日志记录(此时你是否需要对每一个方法添加日志的记录?)
  5. # 第二天CTO 突然改变主意说 原来的方法添加日志记录改为 mysql 记录(此时你是否又要修改每一个方法的日志记录??)
  6. # 我知道你此时此刻一定会想,我可以写一个日志记录方法,让每一个方法内部调用这个方法(很不错的想法)
  7. # 第三天 你的公司cto 告诉你,我的日志一定要记录那些方法执行的开始和结束时间。(是不是有点懵X了?你该怎么办??)

  1.4 怎么用装饰器

  1. # 是否是和上面的那个闭包函数很像呀(其实装饰器就是闭包函数的一种运用)
  2. # 装饰器语法糖:
  3. # 在被装饰对象的正上方一行写@装饰器的名字
  4. # @auth ==> func = auth(func)
  1. login_status = {
  2. 'user':None,
  3. 'status':None
  4. }
  5.  
  6. def login(user:str,pwd:str):
  7. if user == 'jmz' and pwd =='':
  8. login_status['user']=user
  9. login_status['status']=True
  10. return True
  11. else:
  12. return False
  13.  
  14. # 认证用户是否登录成功
  15. def auth(func):
  16. def wrapper(*args,**kwargs):
  17. if login_status['user'] and login_status['status']:
  18. return func(*args,**kwargs)
  19. else:
  20. uname = input('username>>').strip()
  21. upwd = input('password>>').strip()
  22. res =login(uname,upwd)
  23. if res:
  24. return func(*args, **kwargs)
  25. else:
  26. print('认证失败')
  27. return wrapper
  28.  
  29. @auth
  30. def index():
  31. print('from index')
  32.  
  33. @auth
  34. def cat():
  35. print('form cat')
  36.  
  37. index()
  38. cat()

怎么使用装饰器

  1.5 有参装饰器

  1. # 上面的装饰器只是使用了固定的用户jmz,登录,而且没有实现以哪种方式 验证(文件方式,还是mysql方式)
  2. # 如果我需要暂时以文件的方式验证,后期再改为使用mysql 方式验证该如何使用??? (尽量减少代码的修改)
  3. # 要求:
  4. # 1、验证的方式是不固定的
  5. # 2、使用的装饰器要兼顾至少两种以上的验证方式
  6. # 3、需要能够随时给方法添加验证或撤销验证
  1. login_status = {
  2. 'user':None,
  3. 'status':None
  4. }
  5.  
  6. def login(user:str,pwd:str,type='file'):
  7. if type == 'file':
  8. # 假设这就是文件认证
  9. if user == 'jmz' and pwd == '':
  10. login_status['user'] = user
  11. login_status['status'] = True
  12. return True
  13. else:
  14. return False
  15. elif type =='mysql':
  16. # 假设这就是mysql认证
  17. if user == 'jmz' and pwd == '':
  18. login_status['user'] = user
  19. login_status['status'] = True
  20. return True
  21. else:
  22. return False
  23.  
  24. # 认证用户是否登录成功
  25. def auth(type='file'):
  26. def auth2(func):
  27. def wrapper(*args,**kwargs):
  28. if login_status['user'] and login_status['status']:
  29. return func(*args,**kwargs)
  30. else:
  31. uname = input('username>>').strip()
  32. upwd = input('password>>').strip()
  33. res =login(uname,upwd,type)
  34. if res:
  35. return func(*args, **kwargs)
  36. else:
  37. print('认证失败')
  38. return wrapper
  39. return auth2
  40.  
  41. @auth('file')
  42. def index():
  43. print('from index')
  44.  
  45. @auth('file')
  46. def cat():
  47. print('form cat')
  48.  
  49. index()
  50. cat()

有参装饰器

二、迭代器

  2.1 什么是迭代器?

    迭代的工具:

      迭代是一个重复的过程,每一次的重复都是基于上一次的结果进行的      

  1. # 这不是迭代
  2. while True:
  3. print('....')

  2.2 为什么要使用迭代器?

    找到一种不依赖于索引的迭代的方式?

  1. # 1、列表是自带索引的,那么如何迭代没有索引的呢???(禁止使用for)
  2. l = ['a','b','c']
  3. k = 0
  4. while k<len(l):
  5. print(l[k])
  6. k+=1
  7.  
  8. # 2、如何循环取一个无限大的值?
  9. # 如果使用上面的方法显然是不现实的,因为你的列表是存不下无限大的值的(列表的数据占着内存的空间)
  10.  
  11. # 那怎么办呢?

  2.3 怎么使用迭代器?

    2.3.1 可迭代对象

        python 中,但凡内置__iter__方法的,都是可迭代对象

  1. a = 1
  2. b = 1.1
  3. # 以下都是可以使用__iter__ 方法
  4. c = 'abcd'
  5. #c.__iter__()
  6. d = ['a','b','c']
  7. # d.__iter__()
  8. e = ('a','b','c')
  9. # e.__iter__()
  10. f = {'a':1,'b':2}
  11. # f.__iter__()
  12. g={'a','b','c'}
  13. # g.__iter__()
  14. h=open('a.txt','r') # 本身就是一个迭代器对象

     2.3.2 迭代器对象       

  1. # 可迭代对象:在python中但凡有内置方法__iter__的对象,都是可迭代对象
  2. # 迭代器对象 :
  3. # 执行可迭代对象下__iter__方法后得到迭代器对象
  4. # 迭代器对象的内置方法
  5. # __next__
  6. # __iter__方法,执行该方法得到仍然是迭代器本身,干什么用??(等下解释)
  7.  
  8. # 有了迭代器我们就不需要依赖索引取值了
  1. # 注意:
    #      1、迭代器对象一定是对迭代对象
    #      2、可迭代对象不一定是迭代器对象
  1.  
  1. dic = {'a':1,'b':2,'c':3,'d':4}
  2. iter_obj = dic.__iter__()
  3. print(next(iter_obj)) # a
  4. print(next(iter_obj)) # b
  5.  
  6. iter_obj1 = dic.__iter__() # 重新 做了一次迭代器对象操作
  7. print(next(iter_obj1)) # a。
  8.  
  9. iter_obj = iter_obj.__iter__() # iter_obj.__iter__() is iter_obj #True
  10. #iter_obj.__iter__() 无论执行多少次都是本身
  11. print(next(iter_obj)) # c # 会继续给予上一次的操作继续执行
  12. print(next(iter_obj)) # d

__iter__ ,迭代器对象执行后任然是本身

  1. #for循环的底层运行机制:for循环可以称之为迭代器循环
  2. #1、先调用in后那个对象的__iter__方法,得到该对象的迭代器对象
  3. #2、执行迭代器对象的__next__方法,将得到的返回值赋值in前面的变量名,然后执行一次循环体代码
  4. #3、循环往复,直到取干净迭代器内所有的值,自动捕捉异常结束循环
  5. dic = {'a':1,'b':2}
  6.  
  7. iter_obj = dic.__iter__()
  8. while True:
  9. try :
  10. print(dic[iter_obj.__next__()])
  11. except StopIteration:
  12. break
  13.  
  14. for k in dic: #iter_obj=dic.__iter__()
  15. print(dic[k])

for 循环实现原理

   2.4 总结

  1. # 优点:
  2. # 1、不依赖于索引的迭代取值
  3. # 2、节省内存,计算取值
  4.  
  5. # 缺点:
  6. # 1、无法获取长度
  7. # 2、只能next,不能向上取值,只能想下直至结束

迭代器的优缺点

三、生成器

  3.1 什么是生成器 

  1. # 函数内部含有yield关键字,那么该函数() 即为生成器。
  2. # 自定义迭代器
  3.  
  4. def func():
  5. print('first')
  6. yield 1
  7. print('second')
  8. yield 2
  9. print('third')
  10. yield 3
  11.  
  12. f = func()
  13. print(f) #<generator object func at 0x0000000001DF0DB0>

  3.2 生成器的使用方式

  1. # yield 返回值操作
  2. # 生成器就是迭代器,所以用法与迭代器一样
  3.  
  4. # 仿range函数
  5. def range(start:int,end:int,step=1):
  6. while start < end:
  7. yield start # 当一次next 执行到这里时便会返回start,并停止,下一次操作会从本次停止的地方继续往下执行,
  8. start += step # 直到再次遇到 yield 再停止,返回后面的值
  9.  
  10. num = range(1,6,2)
  11. print(num.__next__())
  12. print(num.__next__())
  13. print(num.__next__())
  14.  
  15. # yield : 具有停止本次操作,并return yield 后面的值,与return的返回值一样

生成器使用方式一

  1. # yield 传值操作
  2. def doing(name):
  3. print('%s开始干活了'%name)
  4. thing_list = set()
  5. while True:
  6. do_thing = yield thing_list # 返回thing_list
  7. print('%s 正在%s'%(name,do_thing))
  8. thing_list.add(do_thing)
  9.  
  10. xiaoming = doing('xiaoming')
  11. next(xiaoming) # 第一次使用,需暂停到yield 那边
  12. print(xiaoming.send('做饭')) # 先给yield 传值, 之后再接受执行到下一个yield的返回值
  13. print(xiaoming.send('吃饭'))
  14. print(xiaoming.send('干活'))
  15. print(xiaoming.send('睡觉'))
  16. xiaoming.close() # 关闭生成器
  17. xiaoming.send('起床时') # 此时无法再传值执行,并且报错

生成器使用方式二

  3.3 总结

  1. # 1、可以像return 一样,返回值,但又可以多次返回
  2. # 2、可以挂起/保存函数的当前状态,可以达到随用随启动的程度
  3. # 3、可以多次传值操作

四、练习

  1. # 作业一:写一个取基数的操作 (迭代器)
  2. # 作业二:咖啡3元,糖0.5元 牛奶2元,平时咖啡单点的,活动需要,需加糖与牛奶捆绑销售(装饰器)
  3. # 作业三:用户购买商品,以邮箱或短信的形式通知(装饰器)
  1. #作业一
  2. def jishu():
  3. num = 1
  4. while True:
  5. is_true = True
  6. if num > 1:
  7. count = 2
  8. while count < num - 1:
  9. if num%count==0:
  10. is_true = False
  11. break
  12. count +=1
  13. if is_true:
  14. yield num
  15. num +=1
  16.  
  17. num = jishu()
  18. print(next(num))
  19. print(next(num))
  20. print(next(num))
  21. print(next(num))
  22. print(next(num))
  23.  
  24. #作业二
  25. def sugar(func):
  26. def wrapper(*args,**kwargs):
  27. res = func(*args,**kwargs)
  28. res += 0.5
  29. return res
  30. return wrapper
  31.  
  32. def milk(func):
  33. def wrapper(*args,**kwargs):
  34. res = func(*args,**kwargs)
  35. res += 2.5
  36. return res
  37. return wrapper
  38.  
  39. @sugar
  40. @milk
  41. def coffee():
  42. return 3
  43.  
  44. print(coffee())
  45.  
  46. #作业三
  47. def notice(type='email'):
  48. def shopping(func):
  49. def wrapper(*args,**kwargs):
  50. if type == 'email':
  51. print('邮箱通知成功')
  52. elif type == 'sms':
  53. print('短信通知成功')
  54. return func(*args,**kwargs)
  55. return wrapper
  56. return shopping
  57.  
  58. @notice('sms')
  59. def shopping(good):
  60. print('成功购买了%s商品'%good)
  61.  
  62. shopping('电脑')

作业

五年级--python函数高级运用的更多相关文章

  1. [Python学习笔记][第五章Python函数设计与使用]

    2016/1/29学习内容 第四章 Python函数设计与使用 之前的几页忘记保存了 很伤心 变量作用域 -一个变量已在函数外定义,如果在函数内需要修改这个变量的值,并将这个赋值结果反映到函数之外,可 ...

  2. python高级(五)—— python函数(一等对象)

    本文主要内容 一等对象 普通函数 & 高阶函数 可调用对象 & 自定义可调用类型 函数内省 函数注释 python高级——目录 文中代码均放在github上:https://githu ...

  3. python函数高级特性

    掌握了Python的数据类型.语句.函数,基本可以编写出很多有用的程序了.但是Python中,代码不是越多越好,而是越少越好.代码不是越复杂越好,而是越简单越好.基于这一思想,我们来介绍python中 ...

  4. 四年级--python函数基础用法

    一.函数的定义,调用和返回值 1.1 语法 def 函数(参数一,参数二...): ''' 文档注释 ''' 代码逻辑一 代码逻辑二 .... return 返回值 1.2 定义函数的三种形式 说明: ...

  5. Python —— 函数高级特性(切片、迭代、列表生成式、生成器、迭代器)

    一.切片(Slice) 在很多编程语言中,针对字符串提供了很多截取函数(i.e.  substring),目的就是对字符串切片.python中没有针对字符串的截取函数,需要通过“切片”来完成. 取一个 ...

  6. 12、Python函数高级(命名空间、作用域、装饰器)

    一.名称空间和作用域 1.命名空间(Namespace) 命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空 ...

  7. Python函数高级

    函数对象 在面向对象编程中 一切皆对象 函数在python中是第一类对象 函数可以这么用 可以被引用 def func(): print('hello world !') ​ f=func f() 可 ...

  8. python3笔记十五:python函数

    一:学习内容 函数概述 函数的参数与返回值 参数值传递和引用传递 关键字参数 默认参数 不定长参数 二:函数概述 1.本质:函数就是对功能的封装 2.优点: 简化代码结构,增加了代码的复用度(重复使用 ...

  9. (五)、python 函数

    一.函数 def 函数名(参数): ... 函数体 ... 返回值 函数的定义主要有如下要点: def:表示函数的关键字 函数名:函数的名称,日后根据函数名调用函数 函数体:函数中进行一系列的逻辑计算 ...

随机推荐

  1. ROS(indigo)_turtlebot仿真示例包括stage和gazebo

    ROS(indigo)_turtlebot仿真示例包括stage和gazebo 现上参考网址: turtlebot:http://wiki.ros.org/Robots/TurtleBot stage ...

  2. 利用HTP工具包开发报表

    利用这种方式的优点是不需要跑请求就可以打印报表 工具包中常用程序说明 htp.print 语法   htp.print (cbuf | dbuf | nbuf); 作用   generates a l ...

  3. “基于数据仓库的广东省高速公路一张网过渡期通行数据及异常分析系统"已被《计算机时代》录用

       今天收到<计算机时代>编辑部寄来的稿件录用通知,本人撰写的论文"基于数据仓库的广东省高速公路一张网过渡期通行数据及异常分析系统",已被<计算机时代>录 ...

  4. 手把手带你画一个漂亮蜂窝view Android自定义view

    上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义vi ...

  5. [前端]Emmet 基本语法快查

    Emmet 是一种快速写html的语法,通过几个简单的缩写,就可以拓展成html标签,工作中写html多多少少会有一些,使用的语法都是基础语法,这里总结下最常用的几个,备查. 这个插件支持非常多的ID ...

  6. 《java入门第一季》之面向对象(如何使用帮助文档)

    1:打开帮助文档 2:点击显示,找到索引,看到输入框 3:知道你要找谁?以Scanner举例 4:在输入框里面输入Scanner,然后回车 5:看包 java.lang包下的类不需要导入包,其他的全部 ...

  7. Android4.0Sd卡移植之使用vold自动挂载sd卡

    在cap631平台上移植android4.0,发现内核驱动没有任何问题,能够读写,当总不能挂载. 后来发现是因为自动挂载需要vold的支持.vold程序负责检查内核的 sysfs 文件系统,发现有SD ...

  8. 【Matlab编程】生日快乐歌(显示歌词)—matlab版

    clear all A4=440;%标准音A4 不同的曲调音调不同scale的取值范围不同 pt=44100;p0=pt/2;%频率 scale=A4/2^(9/12)*2.^((-12:11)/12 ...

  9. 中文注释 MariaDB my.cnf 大型服务器配置模板

    文件如下所示,请根据需要进行修改: 翻译日期: 2014年5月22日 翻译人员: 铁锚 # /usr/share/mysql/my-huge.cnf # MariaDB 配置文件 示例模板(huge, ...

  10. HBase数据字典

    数据字典用来存储了系统的元数据.HBase的元数据包括:用户表的定义.表的切分方案.分片的分布情况(即分片分布在哪个regionserver上).分片对应的数据文件和日志文件.其中,分片和数据文件的映 ...