博客园

3、装饰器、迭代器、生成器

>>>>>>>>>>>>>>>装饰器<<<<<<<<<<<<<<

1、什么是装饰器

  装饰器就是一个用来为被装饰对象添加新功能的工具

2、为何要用装饰器

  开放封闭原则:一旦软件上线运行之后,应对需改的源代码封闭,对扩展功能开放
  
  原则:
        1、不修改函数内的源代码
        2、不修改函数的调用方式
  装饰器就是在遵顼原则1和2的前提下,为被装饰对象添加新功能

3、如何实现装饰器

需求:为函数index添加运行时间的功能

源代码:

import time
      def index():
            time.sleep(1)
            print('你真帅')

      index()

装饰器装饰:

import time
      def index():
            time.sleep(1)
            print('你真帅')  源代码不变

开始装饰


  1    def outter(func):      func =被装饰对象 index函数的内存地址
  2          def wrapper(*args,**kwargs):
  3                start time.time()
  4                res = func(*args,**kwargs)  被装饰对象index函数的内存地址(x,y,z)
  5                stop time.time()
  6                print(('run time is %s')%(stop - start))
  7                return res  返回结果也做到和 index 一样
  8          return wrapper
      
  9    index = outter(index)   outter(被装饰对象index函数的内存地址) -> 返回wrapper函数的内存地址 -> index = wrapper函数的内存地址 
  10   index()    调用方式不变  表象是index本质上是wrapper 

>>>>>>>>>>装饰器语法糖<<<<<<<<<<<<

装饰器语法糖是装饰器的,为了更简单漂亮的使用装饰器


import time
from functools import wraps   将wrapper的一些其他参数 也都变成index 更完美的装饰index 和 @wraps 一起使用

def outter(func):  # func = 被装饰对象index函数的内存地址
    @wraps(func)
    def wrapper(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)  # 被装饰对象index函数的内存地址(x,y,z)
        stop = time.time()
        print('run time is %s' %(stop - start))
        return res
    return wrapper  # 千万别加括号

@outter  # index = outter(index)  # outter(被装饰对象index函数的内存地址) -> 返回wrapper函数的内存地址---> index = wrapper函数的内存地址
def index():  # index = 被装饰对象index函数的内存地址
    """这是index函数"""
    time.sleep(1)
    print('from index')

@outter  # home = outter(home)
def home(name):
    time.sleep(2)
    print("welcome %s to home page" %name)
    return 123

无参装饰器的模板 记住就好


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

例 :登录程序


def login(func):
      def wrapper(*args,**kwargs):
            name = input('name>>>>':)
            pwd = input('pwd>>>>>:')
            if name == 'liu' and pwd == '123':
                  res = func(*args,**kwargs)
                  return res
      return wrapper
@login
def index():
      print('index')
index()

>>>>>>>>迭代器<<<<<<<<<

1、什么是迭代器

  迭代器就是指迭代取值的工具

  ####什么是迭代?
        迭代就算一个重复取值的过程,但是每一次都在上一次的基础上进行的

比如:

nums = [111,22,333]
      def get(l):
            i = 0
            while i < len(l)
            print(l[i])
            i += 1
      get(mus)

看到这个有木有想到什么。没错 就是之前的 for 遍历循环,for 循环的本质就是运用迭代器

2、为何要用迭代器

####1、迭代器提供了一种不依赖于索引的、通用的迭代取值方案
####2、节省内存

3、如何用迭代器

####可迭代的对象
    1、内置有__iter__方法的对象都叫可迭代的对象

    调用可迭代对象的__iter__方法,返回的是它的迭代器

####迭代器对象
    1、内置有__next__方法
    2、内置有__iter__方法

    调用迭代器对象的__iter__方法得到的它自己,就跟没调用一样
    调用迭代器对象的__next__方法返回下一个值,不依赖索引
    可以一直调用__next__直到取干净,则抛出异常StopIteration

内置的 类型都是可迭代对象
字符串str 列表list 字典dict 集合set 元组tuple
文件本身就是一个迭代器

在使用while迭代对象的时候


nums_iter = iter(nums)
 while True:
     try:
         res = next(nums_iter)
         print(res)
     except StopIteration: # 取完结束 防止报错崩溃
         break

而 for 的强大在于包含了这些内容

 1、先调用in后那个对象的__iter__方法,拿到迭代器对象
 2、 res = next(迭代器对象),执行一次循环体代码
 3、循环往复步骤2,直到值取干净抛出异常StopIteration,for会捕捉异常结束循环
for res in nums:
    print(res)

<<<<<<<<<<生成器>>>>>>>>>>

在使用函数的时候 使用return 可以提返回值 但是return 只能返回一次,后面程序会停止运行
但是有个一函数 yield 可以返回多次,可以暂停函数的运行!!!!

yield 与 return的异同

相同点:返回值层面用法一样
不同点:return只能返回值一次,而yield可以返回多次
比如
def func():
print('xxx')
yield 111
print('yyy')
yield 222
print('zzz')
yield 333
print('mmmm') 最后一行代码mmm 不会被打印出来
当函数内出现yield关键字,再调用函数并不会触发函数体代码的运行,会返回一个生成器
g = func()
print(g) # 生成器就是一种自定义的迭代器

使用yield 造成一个无限循环的老母鸡 不占用大量空间
def func():
res = 1
while True:
yield res
res += 1

g = func()

print(next(g))
print(next(g)) 取一次 只取一个数 就会遇到 yield 暂停

扩展

nums =[111,22,33]
x = iter(nums) x= 迭代器
for res in x: # x.iter()是返回本身,循环完了
print(res)
print('='*50)

for res in x: # x.iter() 所以本次不会再取到数
print(res)

for res in nums: # nums.iter()是生成一个迭代器
print(res)
print('='*50)
for res in nums: # nums.iter()又生成一个新的迭代器
print(res)

路漫漫其修远兮,吾将上下而求索!!!

加油吧!

posted @ 2020-12-30 15:51  小刘学python  阅读(112)  评论(0编辑  收藏  举报