前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python系列】为啥老问装饰器、迭代器、生成器?

【Python系列】为啥老问装饰器、迭代器、生成器?

作者头像
用户9913368
发布2022-08-13 16:20:21
5950
发布2022-08-13 16:20:21
举报
文章被收录于专栏:嘎嘎软件测试

目录

一、装饰器

二、迭代器

三、生成器

好麻,最近整理下Python学习笔记,把面试常问的几个装饰器、迭代器、生成器总结一下。

一、装饰器

装饰器定义:装饰器便于代码复用, 将函数作为参数传给装饰器函数, 拓展原来函数功能的一种函数。

装饰器作用:装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能(增强函数功能但是又不修改原函数, 抽离函数中与函数本身无关的功能进行复用)。

应用场景:插入日志、性能测试、事务处理、 Web权限校验、Cache等。

代码语言:javascript
复制
"""
1、无参函数装饰器
把@funA放到funA_test()函数的定义处,相当于执行了语句:funA_test = funA(funA_test)
"""
def funA(func):
    print('1、装饰器函数 funA 增强 %s()' % func.__name__)
    func()

@funA
def funA_test():
    print('1、原函数 funA_test')
    
funA_test()
    
输出结果:
1、装饰器函数 funA 增强 funA_test()
1、原函数 funA_test
代码语言:javascript
复制
"""
2、不定长参数函数装饰器
wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。
"""
def funB(func):
    def wrapper(*args, **kwargs):
        print('2、装饰器函数 funB 增强 %s()' % func.__name__)
        func(*args, **kwargs)
    return wrapper


@funB
def funB_test(x, y):
    print('2、原函数 funB_test', x, '+', y, '=', x + y)
    
funB_test(2, 4)
       
输出结果:
2、装饰器函数 funB 增强 funB_test()
2、原函数 funB_test 2 + 4 = 6

二、迭代器

1、迭代器

迭代器定义:迭代器(Iterator)是访问集合内元素的一种方式,提供了一种遍历序列对象的方法。一个类(对象)只要含有__iter__、__next__两个方法,就将其称为迭代器。

迭代器作用:迭代器最核心的功能就是可以通过__next__方法的调用来返回下一个值。而这个值不是从已有的数据中读取的,而是通过程序按照一定的规则生成的。这也就意味着我们可以不再依赖一个现存的数据集合来存放数据,而是边用边生成,这样的好处就是可以节省大量的内存空间。

2、可迭代对象

一个对象只要含有__iter__方法,就将其称为可迭代对象。

Python可迭代对象有str(字符串)、list(列表)、tuple(元组)、dirt(字典)、set(集合)等。

3、总结

1.可迭代对象不一定是迭代器。

2.迭代器一定是可迭代对象。

3.容器类型(str list tuple dict set)是可迭代对象但不是迭代器。

代码语言:javascript
复制
# 定义一个迭代器
class IterDemo:
    def __iter__(self):
        self.a = 1
        return self  # __iter__ 方法返回了实例本身 self,也就是说返回了一个迭代器,所以 IterDemo 的实例 iterDemo 也是一个「可迭代对象」

    def __next__(self):
        x = self.a
        self.a += 1
        if self.a == 10:
            raise StopIteration()  # 异常用于标识迭代的完成,防止出现无限循环的情况
        return x


def iter_demo():
    iterDemo = IterDemo()
    it = iter(iterDemo)  # 创建迭代器对象

    print('x = ', it.__next__())  # 输出迭代器的下一个元素
    print('x = ', it.__next__())  # 输出迭代器的下一个元素
    print('x = ', it.__next__())  # 输出迭代器的下一个元素

    print('y = ', next(it))  # 输出迭代器的下一个元素
    print('y = ', next(it))  # 输出迭代器的下一个元素
    print('y = ', next(it))  # 输出迭代器的下一个元素

    for i in it:
        print('z = ', i)

输出结果:
x =  1
x =  2
x =  3
y =  4
y =  5
y =  6
z =  1
z =  2
z =  3
z =  4
z =  5
z =  6
z =  7
z =  8
代码语言:javascript
复制
# isinstance()检查对象是否是 类/子类 的实例
def isinstanc_demo():
    lisTest = [1, 2, 3]  # 可迭代的
    lisTest1 = 1  # 不可迭代的
    print("判断是否是可迭代的对象:", isinstance(lisTest, Iterable))  # Iterable(可迭代对象)
    print("判断是否是迭代器:", isinstance(lisTest, Iterator))       # Iterator(迭代器)
    print("判断是否是迭代器:", isinstance(IterDemo(), Iterator))    # Iterator(迭代器)


输出结果:
判断是否是可迭代的对象:True
判断是否是迭代器:False
判断是否是迭代器:True
代码语言:javascript
复制
def demo():
    listTest = ['a', 'b', 'c']

    # 迭代遍历
    it = iter(listTest)  # 创建迭代器对象
    print('x= ', it.__next__())

    print('y=', next(it))

    for i in it:
        print("z =", i)  # 输出迭代器的下一个元素

    # 正常遍历
    for j in listTest:
        print("j =", j)
        
输出结果:
x=  a
y= b
z = c
j = a
j = b
j = c

三、生成器

生成器定义:一边循环一边计算的机制,称为生成器(generator)。生成器(generator)也是一种迭代器,在每次迭代时返回一个值,直到抛出 StopIteration 异常。

生成器作用:列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。如:仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。如果列表元素按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。

代码语言:javascript
复制
# 创建生成器方式1:把一个列表生成式的[]改成(),就创建了一个generator
# l是一个list,而g是一个generator
def demo():
    l = [x * x for x in range(10)]
    print(l)

    g = (x * x for x in range(10))

    print(g)  # 打印的是一个对象

    print('x =', next(g))
    print('x =', next(g))
    print('x =', next(g))

    print('y =', g.__next__())
    print('y =', g.__next__())
    print('y =', g.__next__())

    for i in g:
        print('z =', i)
        
    g.close()  # 关闭生成器

输出结果:
x = 0
x = 1
x = 4
y = 9
y = 16
y = 25
z = 36
z = 49
z = 64
z = 81
代码语言:javascript
复制
# 创建生成器方式2:yield
def yield_demo():
    for i in range(10):
        yield i

def yield_demo_test():
    yie = yield_demo()

    print('x =', next(yie))
    print('x =', next(yie))
    print('x =', next(yie))

    print('y =', yie.__next__())
    print('y =', yie.__next__())
    print('y =', yie.__next__())

    for i in yie:
        print('z =', i)
        
输出结果:
x = 0
x = 1
x = 2
y = 3
y = 4
y = 5
z = 6
z = 7
z = 8
z = 9
代码语言:javascript
复制
相关代码已经放到 https://gitee.com/weimenghua/Learn-Python/tree/master/base,decorator_demo.py 、generator_demo.py 、iteration_demo.py。

总结:因为在自动化测试中,装饰器是非常重要的,它可以帮助我们将一个公共部分抽象出来,有点类似于切面编程(AOP),可以让开发者更专注于业务逻辑。迭代器和生成器可以节省大量内存空间,但这块我还没有深刻的理解。

https://www.processon.com/view/link/615eae81e0b34d06f3dcdf4b

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嘎嘎软件测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档