【Python13】迭代器、生成器与yield关键字、闭包、装饰器

1. 迭代器


  • 是访问集合元素的一种方式。
  • 可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 字符串,列表或元组对象都可用于创建迭代器
  • 迭代器有两个基本的方法:
    • iter()
    • next()

实例1

list=[1,2,3,4]
# 创建迭代器对象
it = iter(list)
# 输出迭代器的下一个元素
print (next(it))  # 1
print (next(it))  # 2

实例2:for语句遍历

list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
    print (x, end=" ")
# 1 2 3 4

2. 生成器与yield关键字


  • 生成器(generator)是一个用于创建迭代器的简单而强大的工具。 它们的写法类似于标准的函数,
  • 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行
  • 它会记住上次执行语句时的所有数据值

生成器的特点

●解耦,爬虫与数据存储解耦;
●减少内存占用,随时生产,即时消费,不用堆积在内存当中;
●可不终止调用,写上循环,即可循环接收数据,对在循环之前定义的变量,可重复使用;
●生成器的循环,在yield 处中断,没那么占cpu


实例3

sum(i*i for i in range(10))
# 285

实例4:含有 yield 关键字

#yield:遇到yield则停止执行代码, 当再次调用next方法时,会从上次停止的地方继续执行,遇到yield停止
def login():
    print('step 1')   # 'step 1'
    yield 1           # output 1
    print('step 2')
    yield  2
    print('step 3')
    yield 3
# 如果函数里面有yield关键字,函数的返回值就是一个生成器
g = login()
print(next(g))
print(next(g))
执行结果为:
# step 1
# 1
# step 2
# 2

3. 闭包


  1. 函数里面嵌套函数
  2. 外部函数的返回值是内部函数的引用
  3. 内部函数可以使用外部函数的变量

实例5

def timeit(name):
    def wrapper():
        print('wrapper ' + name)
    print('timeit')
    return wrapper

in_fun = timeit(name='westos')  # wrapper函数, in_fun实质上就是wrapper函数
in_fun()
执行结果为:
# timeit
# wrapper westos

4. 装饰器


  1. 装饰器: 用来装饰函数的工具。
  2. 功能: 在不改变源代码的情况下, 添加额外功能(eg: 计算运行时间, 记录日志,权限判断)的工具.
  3. 如何实现装饰器? 基于闭包的

实例6

import time
def timeit(f):      # f=add
    def wrapper(x, y):
        start = time.time()
        result = f(x, y)   # f实质上是add函数
        end = time.time()
        print("函数运行的时间为: %.4f" %(end-start))
        return  result
    return wrapper
@timeit   # 1. 语法糖, add=timeit(add)
def add(x, y):
    return x + y
result = add(1, 3)
print(result)
执行结果为:
函数运行的时间为: 0.0000
4


4.1 万能模板


装饰器的万能模板:
def 装饰器名称(f):
    @wraps(f)  # 保留被装饰函数的属性信息和帮助文档
    def wrapper(*args, **kwargs):
        # 执行函数之前做的事情
        result = f(*args, **kwargs)
        # 执行函数之后做的事情
        return  result
    return  wrapper

实例7:计算函数的运行时间

扫描二维码关注公众号,回复: 12678764 查看本文章

@wraps 接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性

import time
from functools import  wraps
def timeit(f):
    """计时器的装饰器"""
    @wraps(f)  # 保留被装饰函数的属性信息和帮助文档
    def wrapper(*args, **kwargs):
        """wrapper内部函数"""
        start = time.time()
        result = f(*args, **kwargs)
        end = time.time()
        print(f"函数{f.__name__}运行时间为{end-start}秒")
        return  result
    return  wrapper

@timeit
def login():
    print('login....')
login()

执行结果为:
# login....
# 函数login运行时间为0.0秒


4.2 含参数的装饰器


实例8:计算函数的运行时间

import  time
from functools import  wraps
def timeit(args='seconds'):
    def desc(f):
        """计时器的装饰器"""
        @wraps(f)  # 保留被装饰函数的属性信息和帮助文档
        def wrapper(*args, **kwargs):
            """wrapper内部函数"""
            start = time.time()
            result = f(*args, **kwargs)
            end = time.time()
            if args == 'seconds':
                print(f"函数{f.__name__}运行时间为{end-start}秒")
            elif args == 'minutes':
                print(f"函数{f.__name__}运行时间为{(end-start)/60}秒")
            return  result
        return  wrapper
    return  desc

@timeit(args='minutes')  # timeit()  @desc===> login=desc(login)
def login():
    """login desc"""
    print('login....')

login()

实例9:爬取图片

import  time
from functools import  wraps
def timeit(args='seconds'):
    def desc(f):
        """计时器的装饰器"""
        @wraps(f)  # 保留被装饰函数的属性信息和帮助文档
        def wrapper(*args, **kwargs):
            """wrapper内部函数"""
            start = time.time()
            result = f(*args, **kwargs)
            end = time.time()
            if args == 'seconds':
                print(f"函数{f.__name__}运行时间为{end-start}秒")
            elif args == 'minutes':
                print(f"函数{f.__name__}运行时间为{(end-start)/60}秒")
            return  result
        return  wrapper
    return  desc

@timeit
def crawl():
    import  requests
    url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Python.svg/1200px-Python.svg.png'
    content = requests.get(url).content
    with open('doc/python.png', 'wb') as f:
        f.write(content)
        print("下载图片成功")

crawl()


4.3 多装饰器


实例10

from functools import  wraps
def is_login(f):
    # @wraps(f)
    def wrapper(*args, **kwargs):
        print('is_login, 用户是否登录')
        result = f(*args, **kwargs)
        return  result
    return  wrapper

def is_permission(f):
    # @wraps(f)
    def wrapper(*args, **kwargs):
        print('is_permission, 用户是否有权限')
        result = f(*args, **kwargs)
        return  result
    return  wrapper

# 规则: 执行装饰器内容是从上到下。 被装饰的顺序是从下到上。
@is_login
@is_permission
def show_hosts():
    print("显示所有的云主机")

show_hosts()
执行结果为:
# is_login, 用户是否登录
# is_permission, 用户是否有权限
# 显示所有的云主机

猜你喜欢

转载自blog.csdn.net/weixin_46069582/article/details/113740029