前言
简要介绍 装饰器,迭代器以及生成器,以下内容仅供参考
一、装饰器
在原有代码的基础上进行包裹代码,增加功能。1.引入闭包概念
定义:简单来说就是内层函数使用了外层函数的变量,同时内层函数将该函数返回
代码如下(示例):
def warapperTest():
a=10
def inner():
print(a)
return inner# 将内层函数返回
a=warapperTest()# 此时返回的其实是inner函数
a() # 实际执行的是inner()
- 闭包中将内层函数直接返回【即内层函数中的变量调用/修改】
1、将内层函数直接返回,意味着内层函数的运行时间不确定(当外层函数返回后,可以不立即执行),使得在python中会让在内层函数中执行的变量常驻
2、外部无法修改内层函数中调用的变量 - 这就有装饰器的雏形,在本身函数上添加外部函数,同时外部无法修改本身函数的变量
2.装饰器的使用
装饰器的原理,函数类似充当变量被返回。
1、创建方式
- 方式一: 将自身函数充当参数传入装饰器中
def warapperTest(fn): # 将函数充当参数传入,此时是传入的函数没有参数
def inner():
print('warapperTest装饰器之前调用') # 首先执行
fn() # 被装饰的函数执行
print('warapperTest装饰器之后调用') # 在被装饰函数后执行
return inner
def test():
print('这是判定')
test = warapperTest(test) # 装饰类方式一:直接把函数充当参数传入过去,注意不是函数的调用
test()
'''
warapperTest装饰器之前调用
这是判定
warapperTest装饰器之后调用'''
- 方式二:通过注解的方式@装饰器名称
@warapperTest1 # 采用就近原则,先解析靠近test的装饰类,在其基础上再次装饰
@warapperTest # 装饰类方式二
def test():
print('这是判定')
test()
'''
warapperTest1装饰器之前调用
warapperTest装饰器之前调用
这是判定
warapperTest装饰器之后调用
warapperTest1装饰器之后调用
'''
2、被装饰的函数带有参数时
1、上面的方式中,被装饰的函数不带有参数。当带有参数时,过程类似,仔细思索程序从上之下执行,2、则在执行到内部(即上方的inner())函数时,则将被装饰的函数的参数一同传入即可
def wrapperTest2(fn):
def inner(*args, **kwargs):
print(f'这是内部的第一次调用')
fn(*args, **kwargs) # 位置参数和关键字参数,具体使用不在此赘述
print('这是内部的第一次调用')
return inner
@wrapperTest2
def func(name, age):
print(f'姓名{name}年龄{age}')
func('张三', '14') # 在调用是传入
'''
这是内部的第一次调用
姓名张三年龄14
这是内部的第一次调用
'''
3、带有参数的装饰器
1、上述是被装饰的函数带有参数,很容易想到那么这个就是装饰器带有参数2、当装饰器被多个函数所调用时,对待不同的函数选择不同的功能
def wrapper_out(name): # 最简单直接的方式,在最外层再次套一个函数,用于接收装饰器传入的参数
def wrapperTest(fn):
def inner(*args, **kwargs):
print(f"执行调用器之前{name}")
fn(*args, **kwargs)
print("执行调用器之后")
return inner
return wrapperTest
@wrapper_out("abc") # 先执行函数的调用,然后和前面的@组合之后形成语法糖
def test():
print('test')
test()
'''
执行调用器之前abc
test
执行调用器之后
'''
二、迭代器
1.迭代器概念
1、迭代器最大的作用个就是统一了容器类型循环遍历的标准
"__iter__" in dir(s) # 判定s类型中是否有_iter_,有则表示可以迭代
2、常用的迭代方式
1、for循环和while方式一个一个拿
for i in [1,2,3]:
print(i)
lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
try:
i = lst_iter.__next__()
print(i)
except StopIteration:
break
'''
结果均为:
1
2
3
'''
2、list可以一次性把迭代器中的内容全部拿空. 并装载在一个新列表中
s = "学习使我快乐,我爱学习".__iter__()
print(list(s)) # ['学', '习', '使', '我', '快', '乐', ',', '我', '爱', '学', '习']
# 上面不添加._iter_()是一样的
三、生成器
1、和上面迭代器不同的是,迭代器只要开始取数据(不是单独取一个,意思是取了一个,不一定取下一个,但是某时想起来再取),就停不下来,而且需要一次性的分配出足够的空间
1、创建方式
下方的yield和return类似同样具有返回的功能- 方式一:通过生成器函数
def test():
print("学习使我快乐,我爱学习")
yield 111
print("我饿了")
print(test()) # 结果为:<generator object test at 0x009D29C8>
print(test().__next__()) # 结果为:学习使我快乐,我爱学习 111
注:生成器中一次_next_()执行得到的位置
2.方式二:通过生成器表达式
g = (i for i in range(10)) # 生成器
2、生成器的应用
def func():
lst = [1, 2, 3, 4]
lst1 = ['a', 'b', 'c', 'd']
# for item in lst:
# yield item
# for item in lst1:
# yield item
yield from lst # 和上面的结果一样,可把可迭代对象中的每一项分别返回,和上面效果一样
yield from lst1
g=func()
print(g.__next__())
print(g.__next__())
'''
结果
1
2
'''
'''
yield from
在python3中提供了一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回
写两个yield from 并不会产生交替的效果.
'''