[Python][华为云Python编程创造营][学习笔记][12_Python三大神器]

举报
John2021 发表于 2021/11/13 18:45:41 2021/11/13
【摘要】 1,迭代器    1.1,迭代        1.1.1,迭代是Python中用于访问序列结构数据的一种方式            - 当我们用一个循环(比如for循环)来遍历容器(比如列表、元组)中的元素时,这种遍历的过程就叫迭代。    1.2,可迭代对象        1.2.1,可以被for循环遍历的对象成为可迭代对象            - 可迭代对象中需要实现__iter__或...

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来观察

img1.jpg

img2.jpg

img3.jpg

img4.jpg

img5.jpg

img6.jpg

img7.jpg

img8.jpg

img9.jpg

img10.jpg

img11.jpg

img12.jpg

img13.jpg

img14.jpg

img15.jpg

img16.jpg

img17.jpg

img18.jpg

img19.jpg

img20.jpg

img21.jpg

img22.jpg

img23.jpg

img24.jpg

img25.jpg

img26.jpg

img27.jpg

img28.jpg

img29.jpg

img30.jpg

img31.jpg

img32.jpg

img33.jpg

img34.jpg

img35.jpg

img36.jpg

img37.jpg

img38.jpg

img39.jpg

img40.jpg

img41.jpg

img42.jpg

img43.jpg

img44.jpg

img45.jpg

img46.jpg

img47.jpg

img48.jpg

img49.jpg

img50.jpg

img51.jpg

img52.jpg

img53.jpg

img54.jpg

img55.jpg

img56.jpg

img57.jpg

    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,关系

img58.jpg

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
# 我是某胜利队队员大骨
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。