[Python][华为云Python编程创造营][学习笔记][12_Python三大神器]
1,迭代器
1.1,迭代
1.1.1,迭代是Python中用于访问序列结构数据的一种方式
- 当我们用一个循环(比如for循环)来遍历容器(比如列表、元组)中的元素时,这种遍历的过程就叫迭代。
1.2,可迭代对象
1.2.1,可以被for循环遍历的对象成为可迭代对象
- 可迭代对象中需要实现__iter__或者__getitem__方法
1.3,迭代器
1.3.1,迭代器是指遵循迭代器协议(iterator protocol)的对象
- 迭代器协议:实现对象的__iter__和__next__方法,其中__iter__方法返回迭代器对象本身,next()方法返回容器的下一个元素,在没有后续元素时抛出StopIteration异常。
- 可迭代对象不是迭代器。
- 使用iter()获取迭代器对象。
1.3.2,迭代器是一个可以记住遍历的位置的对象
- 迭代器对象从集合的第一个元素开始访问(next),直到所有的元素被访问结束。迭代器只能往前不能后退。
1.3.3,对于迭代器对象,可以使用next方法获取
- 当元素迭代完后会出现StopIteration异常。
# 字符串,列表或者元组对象都可用于创建迭代器
list = [1,2,3,4]
it = iter(list) # 创建迭代器对象
print(next(it)) # 输出迭代器的下一个元素 1
print(next(it)) # 输出迭代器的下一个元素 2
# 迭代器对象可以使用常规for语句进行遍历
list = [1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print(x,end=" ") # 1 2 3 4
# 也可以使用next()函数
import sys # 引入sys模块
list = [1,2,3,4]
it = iter(list) # 创建迭代器对象
while True:
try:
print(next(it),end=" ") # 1 2 3 4
except StopIteration:
sys.exit()
# 创建一个返回数字的迭代器,初始值为1,逐步递增2
class MyNumber:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 2
return x
myclass = MyNumber()
myiter=iter(myclass)
print(next(myiter)) # 1
print(next(myiter)) # 3
print(next(myiter)) # 5
print(next(myiter)) # 7
print(next(myiter)) # 9
# 迭代20次后停止执行
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 10:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x,end=" ") # 1 2 3 4 5 6 7 8 9 10
2,生成器
2.1,生成器(generator)是一类特殊的迭代器
2.1.1,生成器每次在迭代时可以返回一个或多个值,它可以记录当前状态
- 生成器的创建方式:使用yield关键字,使用生成器表达式(推导式)。
2.2,生成器推导式
2.2.1,推导式形式
G = (x*2 for x in range(5))
print(type(G)) # <class 'generator'>
2.2.2,判断是否是生成器
from collections.abc import Generator
G = (x*2 for x in range(5))
res = isinstance(G,Generator)
print(res) # True
2.3,yield创建生成器
2.3.1,使用yield创建生成器
- 通过yield创建一个产生斐波那契数列的生成器
import sys
def fibonacci(n): # 生成器函数 - 斐波那契数列
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a+b
counter += 1
f = fibonacci(10) # f是一个迭代器,由生成器返回生成
while True:
try:
print(next(f),end=" ") # 0 1 1 2 3 5 8 13 21 34 55
except StopIteration:
sys.exit()
2.3.2,为了更好了解yield的工作流程,我们通过Debug来观察
2.4,生成器取值
2.4.1,生成器可以使用next和send取值
- next,获取下一个元素。
- send,获取下一个元素,同时可以向生成器中传递一个值。
- next等同于send(None)。
- 第一次取值时,需要使用next或者send(None)。
2.5,执行过程(1)
2.5.1,下面例子的执行过程
def fib(n):
current = 0
num1, num2 = 0, 1
while current < n:
num = num1 # 1
num1, num2 = num2, num1+num2 # 2
current += 1
yield num # 3
return 'done' # 6
g = fib(5) # 4
next(g) # 5
# 执行过程:-4 -1 -2 -3 -5 -1 -2 ... -6
2.6,执行过程(2)
2.6.1,使用yield声明函数为生成器
2.6.2,当程序执行到yield处时,生成器函数暂停,等待下一次唤醒(next,send)
- 并且返回当前值。
- 和return相似,但是程序暂停而不是结束。
2.7,关系
3,装饰器
装饰器(Decorators)是修改其他函数功能的函数。
3.1,闭包(1)
3.1.1,闭包:是由函数及其相关的引用环境组合而成的实体。
3.1.2,不同编程语言实现闭包的方式是不同的,Python中闭包从表现形式上看,如果在一个内部函数里,对在外部作用域(不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包。
def func(x):
def inner(y):
return x+y
return inner
3.2,闭包(2)
3.2.1,闭包中不可以直接修改外部函数的局部变量
- 类似于不能直接在函数中修改全局变量(可变类型除外),需要使用关键字nonlocal。
3.2.2,闭包的作用
- 当闭包执行完后,仍然能够保持住当前的运行环境。
- 闭包可以根据外部作用域的局部变量来得到不同的结果。
def func1(func):
def inner():
print("func1")
func()
return inner
def func2():
print("func2")
func1(func2)()
3.3,装饰器(1)
3.3.1,装饰器本质上是一个Python函数,可以在不改变代码结构的情况下给代码添加新的功能。
3.3.2,装饰器的工作过程:将被装饰的函数当作参数传递给装饰器函数(名称相同的函数),并返回装饰后被装饰的函数。
3.3.3,装饰器是闭包的一种应用。
3.3.4,装饰器的使用
# @装饰器函数
# def func():
# pass
3.4,装饰器(2)
3.4.1,装饰器的作用
def light(func): # 装饰器函数
print("获得神光棒x1")
def tiga():
func()
print("我是光之巨人")
return tiga()
@light
def person():
print("我是某胜利队队员大骨")
person()
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
# 我是光之巨人
# TypeError: 'NoneType' object is not callable
def light(func): # 装饰器函数
print("获得神光棒x1")
def tiga():
func()
print("我是光之巨人")
return tiga
def person():
print("我是某胜利队队员大骨")
light(person)()
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
# 我是光之巨人
3.5,丢失的信息
3.5.1,装饰器不会改变原有函数代码,但是会丢失一部分信息
- 被装饰函数的元信息会丢失,如:名字、文档字符串、注解和参数签名
def light(func): # 装饰器函数
print("获得神光棒x1")
def tiga():
func()
print("我是光之巨人")
return tiga
@light
def person(): # 被装饰的函数
'''我要打怪兽'''
print("我是某胜利队队员大骨")
person()
help(person)
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
# 我是光之巨人
# Help on function tiga in module __main__:
# tiga()
3.6,wraps
3.6.1,为了保留因为使用装饰器而丢失的信息,可以使用Python中本身提供的装饰器@wraps来解决
from functools import wraps
def light(func):
print("获得神光棒x1")
@wraps(func)
def tiga():
func()
print("我是光之巨人")
return tiga
@light
def person():
'''我想打怪兽'''
print("我是某胜利队队员大骨")
person()
help(person)
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
# 我是光之巨人
# Help on function person in module __main__:
# person()
# 我想打怪兽
3.7,被装饰函数的参数
3.7.1,当被装饰函数拥有参数时,如何在装饰器过程中进行传递?如何构建一个通用的装饰器?
from functools import wraps
def func1(func):
@wraps(func)
def inner(a, b):
print("func1")
func(a, b)
return inner
@func1
def func2(a, b):
print(a+b)
func2(1, 2)
# 输出结果
# func1
# 3
3.8,带有参数的装饰器
3.8.1,如何通过装饰器的参数来控制装饰器?
- 对当前用户增加权限:VIP,SVIP,VIP中P
def Decorator(name=None,level="普通会员"):
def outer(func):
def inner(name):
print("欢迎登陆, %s"%level)
func(name)
return inner
return outer
@Decorator(level="SVIP")
def func(name):
print(name)
func("张三")
# 输出结果
# 欢迎登陆, SVIP
# 张三
- 通过外部参数,返回一个装饰器
3.9,装饰器与类(1)
3.9.1,装饰器不仅可以是函数,还可以是类(如property)
- 同样,装饰器不仅可以修饰函数,还可以修饰类
3.9.2,装饰器装饰类
def singleton(cls,*args,**kw):
instance={}
def _singleton():
if cls not in instance:
instance[cls]=cls(*args,**kw)
return instance[cls]
return _singleton
@singleton
class Singleton(object):
def __init__(self):
self.num_sum=0
def add(self):
self.num_sum=100
4.0,装饰器与类(2)
4.0.1,将装饰器定义为类的形式。
- __call__:魔法方法,可以让类像方法一样被调用。
import time
class Wrapper():
def __init__(self,func):
self.func=func
def __call__(self,*args,**kwargs):
start=time.time()
result=self.func(*args,**kwargs)
end=time.time()
print(end-start)
return result
@Wrapper
def func(num):
time.sleep(3)
return num
func(1) # 3.000171422958374
4.1,多个装饰器
def Tiga(func):
print("给我力量吧,Tiga")
def tiga():
func()
print("获得Tiga的力量")
return tiga
def Dyna(func):
print("给我力量吧,Dyna")
def dyna():
func()
print("获得Dyna的力量")
return dyna
def Gaia(func):
print("给我力量吧,Gaia")
def gaia():
func()
print("获得Gaia的力量")
return gaia
@Tiga
@Dyna
@Gaia
def Z():
print("变身")
Z()
# 输出结果
# 给我力量吧,Gaia
# 给我力量吧,Dyna
# 给我力量吧,Tiga
# 变身
# 获得Gaia的力量
# 获得Dyna的力量
# 获得Tiga的力量
4.2,解除装饰器
from functools import wraps
def light(func):
print("获得神光棒x1")
@wraps(func)
def tiga():
func()
print("我是光之巨人")
return tiga
@light
def person():
print("我是某胜利队队员大骨")
person()
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
# 我是光之巨人
DaGu=person.__wrapped__
DaGu()
# 输出结果
# 获得神光棒x1
# 我是某胜利队队员大骨
- 点赞
- 收藏
- 关注作者
评论(0)