Python三大器--装饰器, 迭代器, 生成器

1. 迭代器
  • 自定义迭代器对象: 在类里面提供__iter__和__next__方法创建的对象就是完整的迭代器(为什么说完整呢?)。
  • 实际上严格意义来说只要类中实现了__iter__方法实现了, 这个类就是迭代器, 它返回了迭代器对象, 但是一个迭代器对象没有实现__next__方法, 这个迭代器是无法正常使用的, 这里验证了上面的结果
class MyIterator(object):
    # 构造方法
    def __init__(self, my_list):
        self.my_list = my_list
        self.current_index = 0
    # 标志1
    def __iter__(self):
        return self
    # 标志2,获取迭代器中下一个值
    def __next__(self):
        if self.current_index < len(self.my_list):
            value = self.my_list[self.current_index]
            # 取值完成以后需要对下标加上1
            self.current_index += 1
            return value
        else:
            # 超出范围抛出停止迭代的异常
            raise StopIteration
# 迭代器被__iter__调用,返回一个迭代器

my = MyIterator([1, 2, 3, 4])
# print(next(my))
# print(next(my))
# print(next(my))
# print(next(my))
# 验证对象是否是迭代器的方法
from collections import Iterable
print(isinstance(my, Iterable))
2. 生成器
  • 把列表推导式的中括号改成小括号创建的对象就是生成器。生成器:生成器是一个特殊的迭代器,也就是说可以使用next和for循环取值
print(type((i for i in range(10))))
# 

yield就是保存当前程序的执行状态, 使用for循环的时候, 每次取一个元素的时候就会计算一次, 用yield实现的generator(生成器)和iterator(迭代器)一样, 它的好处是不用一次计算所有元素, 而是用一次算一次, 大大的节省空间, 由于generator每次计算需要上一次的计算结果, 所以yield就达到了这个作用, 如果用return, 上次的结果就没了.

# 最简单的生成器
def createGenerator():
    my_list = range(3)
    for i in my_list:
        yield i * i
my_generator = createGenerator()
  • 以下代码测试了yield和return不同之处之一—yield后面的代码可以正常执行, return 后面的代码不执行
# 生成器实现斐波那契数列
def fibonacci(num):
    # num: 表示斐波那契数列的个数
    # 保存数列的前两个值
    a = 0
    b = 1
    # 记录生成数列的下标
    current_index = 0
    # 循环判断条件是否成立
    while current_index < num:
        # 记录当前斐波那契数值
        result = a
        # 这里实验了一下, yield和return不同之处之一---yield后面的代码可以正常执行, return 后面的代码不执行
        # yield result
        # 生成下一个斐波那契数值,即b,但下一次输出a
        a, b = b, a + b
        current_index += 1
        # 代码执行到yield会暂停,把结果返回出取,再次启动生 成器的时候会在暂停的位置继续往下执行
        yield result
# 生成器返回类型是特殊的迭代器(生成器)需要for/next()取值
generator = fibonacci(10)
for value in generator:
    print(value)
3. 装饰器有写到过, 不多说直接上代码
# 外函数outer()
def outer():
    # 外函数局部变量,对于内函数来说相当于全局变量(重点理解, 有助于理解闭包的延迟绑定)
    number = 10
    # 内函数
    def inner():
        # 外函数数据的引用
        nonlocal number
        number += 1
    # 返回值是内函数inner的引用
    return inner

# 调用outer函数,用func接收inner函数的引用
func = outer()
# 调用inner函数
func()
def outer(func):
    def inner():
        return func()
    return inner
# 装饰器的使用  @ :相当于 func = outer(func)
# 即把func的引用替换成outer的返回值,也就是内函数的引用
# 然后在内函数中返回原本func的引用的调用,即func的函数体
@outer
def func():
    pass
装饰器的使用场景
def outer(func):
    print('验证前做的事')
    def inner():
        func()
        print('验证后做的事')
    return inner
@outer
def func():
    print('验证代码')
func()
# 装饰器的另一种调用方法
# outer(func)()
装饰器的另一种使用(Flask中会用到)
def outer(func):
    print('验证前做的事')
    def inner():
        func()
        print('验证后做的事')
    return inner
def func():
    print('验证代码')
outer(func)()

你可能感兴趣的:(装饰器,生成器,迭代器)