zoukankan      html  css  js  c++  java
  • python-day13(正式学习)

    闭包函数

    闭包

    闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

    额。。。这里提示一下闭包!=自闭

    img

    为函数传参的两种方式

    使用参数的方式

    def func(x):
        print(x)
    
    
    func(1)
    func(1)
    func(1)
    

    1
    1
    1

    包给函数

    def outter(x):
        x = 1
    
        def inner():
            print(x)
        return inner
    
    
    f = outter(1)
    f()
    f()
    f()
    # 查看闭包的元素
    print(F"f.__closure__[0].cell_contents: {f.__closure__[0].cell_contents}")
    
    1
    1
    1
    f.__closure__[0].cell_contents: 1
    

    装饰器

    什么是装饰器

    器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。

    需要注意的是:

    • 装饰器本身其实是可以任意可调用的对象
    • 被装饰的对象也可以是任意可调用的对象

    为什么要用装饰器

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    48装饰器-bug.jpg?x-oss-process=style/watermark

    怎么用装饰器

    改变源代码

    import time
    
    
    def index():
        start = time.time()
        print('welcome to index')
        time.sleep(1)
        end = time.time()
        print(F"index run time is {start-end}")
    
    
    index()
    
    
    welcome to index
    index run time is -1.0008180141448975
    

    编写重复代码

    import time
    
    
    def index():
        print('welcome to index')
        time.sleep(1)
    
    
    def f2():
        print('welcome to index')
        time.sleep(1)
    
    
    start = time.time()
    index()
    end = time.time()
    print(F"index run time is {start-end}")
    
    start = time.time()
    f2()
    end = time.time()
    print(F"f2 run time is {start-end}")
    
    
    welcome to index
    index run time is -1.0046868324279785
    welcome to index
    f2 run time is -1.000690221786499
    

    第一种传参方式:改变调用方式

    import time
    
    
    def index():
        print('welcome to index')
        time.sleep(1)
    
    
    def time_count(func):
        start = time.time()
        func()
        end = time.time()
        print(f"{func} time is {start-end}")
    
    
    time_count(index)
    
    
    welcome to index
    <function index at 0x102977378> time is -1.000748872756958
    

    第二种传参方式:包给函数-外包

    import time
    
    
    def index():
        print('welcome to index')
        time.sleep(1)
    
    
    def time_count(func):
        # func = 最原始的index
        def wrapper():
            start = time.time()
            func()
            end = time.time()
            print(f"{func} time is {start-end}")
        return wrapper
    
    # f = time_count(index)
    # f()
    
    
    index = time_count(index)  # index为被装饰函数的内存地址,即index = wrapper
    index()  # wrapper()
    
    
    welcome to index
    <function index at 0x102977730> time is -1.0038220882415771
    

    完善装饰器

    上述的装饰器,最后调用index()的时候,其实是在调用wrapper(),因此如果原始的index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。

    import time
    
    
    def index():
        print('welcome to index')
        time.sleep(1)
    
        return 123
    
    
    def time_count(func):
        # func = 最原始的index
        def wrapper():
            start = time.time()
            res = func()
            end = time.time()
            print(f"{func} time is {start-end}")
    
            return res
        return wrapper
    
    
    index = time_count(index)
    res = index()
    print(f"res: {res}")##
    welcome to index
    <function index at 0x102977620> time is -1.0050289630889893
    res: 123
    

    如果原始的index()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有wrapper()=index(),所以给wrapper()方法传参即可。

    import time
    
    
    def index():
        print('welcome to index')
        time.sleep(1)
    
        return 123
    
    
    def home(name):
        print(f"welcome {name} to home page")
        time.sleep(1)
    
        return name
    
    
    def time_count(func):
        # func = 最原始的index
        def wrapper(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            end = time.time()
            print(f"{func} time is {start-end}")
    
            return res
        return wrapper
    
    
    home = time_count(home)
    
    res = home('egon')
    print(f"res: {res}")##
    welcome egon to home page
    <function home at 0x102977378> time is -1.0039079189300537
    res: egon
    

    装饰器语法糖

    在被装饰函数正上方,并且是单独一行写上@装饰器名

    img

    import time
    
    
    def time_count(func):
        # func = 最原始的index
        def wrapper(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            end = time.time()
            print(f"{func} time is {start-end}")
    
            return res
        return wrapper
    
    
    @time_count  # home = time_count(home)
    def home(name):
        print(f"welcome {name} to home page")
        time.sleep(1)
    
        return name
    
    
    @time_count  # index = time_count(index)
    def index():
        print('welcome to index')
        time.sleep(1)
    
        return 123
    
    
    res = home('egon')
    print(f"res: {res}")##
    welcome egon to home page
    <function home at 0x102977620> time is -1.0005171298980713
    res: egon
    

    有参装饰器

    import time
    
    current_user = {'username': None}
    
    
    def login(func):
        # func = 最原始的index
        def wrapper(*args, **kwargs):
    
            if current_user['username']:
                res = func(*args, **kwargs)
    
                return res
    
            user = input('username: ').strip()
            pwd = input('password: ').strip()
            
            engine = 'file'
    
            if engine == 'file':
                print('base of file')
                if user == 'nick' and pwd == '123':
                    print('login successful')
                    current_uesr['usre'] = user
                    res = func(*args, **kwargs)
    
                    return res
                else:
                    print('user or password error')
            elif engine == 'mysql':
                print('base of mysql')
            elif engine == 'mongodb':
                print('base of mongodb')
            else:
                print('default')
    
        return wrapper
    
    
    @login
    def home(name):
        print(f"welcome {name} to home page")
        time.sleep(1)
    
    
    @login
    def index():
        print('welcome to index')
        time.sleep(1)
    
    
    res = index()
    
    username: nick
    password: 123
    base of file
    login successful
    welcome to index
    

    三层闭包

    import time
    
    current_uesr = {'username': None}
    
    
    def auth(engine='file'):
    
        def login(func):
            # func = 最原始的index
            def wrapper(*args, **kwargs):
    
                if current_user['username']:
                    res = func(*args, **kwargs)
    
                    return res
    
                user = input('username: ').strip()
                pwd = input('password: ').strip()
    
                if engine == 'file':
                    print('base of file')
                    if user == 'nick' and pwd == '123':
                        print('login successful')
                        current_uesr['usre'] = user
                        res = func(*args, **kwargs)
    
                        return res
                    else:
                        print('user or password error')
                elif engine == 'mysql':
                    print('base of mysql, please base of file')
                elif engine == 'mongodb':
                    print('base of mongodb, please base of file')
                else:
                    print('please base of file')
    
            return wrapper
    
        return login
    
    
    @auth(engine='mysql')
    def home(name):
        print(f"welcome {name} to home page")
        time.sleep(1)
    
    
    @auth(engine='file')
    def index():
        print('welcome to index')
        time.sleep(1)
    
    
    res = index()
    
    username: nick
    password: 123
    base of file
    login successful
    welcome to index
    

    由于两层的装饰器,参数必须得固定位func,但是三层的装饰器解除了这个限制。我们不仅仅可以使用上述单个参数的三层装饰器,多个参数的只需要在三层装饰器中多加入几个参数即可。也就是说装饰器三层即可,多加一层反倒无用。

    装饰器叠加

    def outter1(func):  # func = wrapper2
        def wrapper1(*args, **kwargs):  # wrapper是未来要运行的函数
            print('------------')
            res = func(*args, **kwargs)  # func是被装饰的函数  # wrapper2
            print('------------')
            return res
    
        return wrapper1
    
    def outter2(func):  # func = index
        def wrapper2(*args, **kwargs):  # wrapper是未来要运行的函数
            print('11111111111111')
            res = func(*args, **kwargs)  # func是被装饰的函数  # index()
            print('11111111111111')
            return res
    
        return wrapper2
    
    # @outter1  # index = outter1(index)
    # @outter2  # index = outter2(index)  # 先运行最下面的装饰器
    # # index
    def index():
        print('index')
    
    # index重新定义的index = outter2(index 真正的index)
    index = outter2(index)   #  index = wrapper2
    # index再一次重新定义的index = outter1(index重新定义的index,即wrapper2)
    index = outter1(index)  # index  = wrapper1
    index()  # wrapper1()
    

    兄弟自求多福!!!(切勿钻牛角尖)

    img

    迭代器

    迭代器:迭代的工具。迭代是更新换代,如你爷爷生了你爹,你爹生了你,迭代也可以说成是重复,并且但每一次的重复都是基于上一次的结果来的。如计算机中的迭代开发,就是基于软件的上一个版本更新。以下代码就不是迭代,它只是单纯的重复

    可迭代对象

    python中一切皆对象,对于这一切的对象中,但凡有__iter__方法的对象,都是可迭代对象。

    # x = 1.__iter__  # SyntaxError: invalid syntax
    
    # 以下都是可迭代的对象
    
    name = 'nick'.__iter__
    lis = [1, 2].__iter__
    tup = (1, 2).__iter__
    dic = {'name': 'nick'}.__iter__
    s1 = {'a', 'b'}.__iter__
    f = open('49w.txt', 'w', encoding='utf-8')
    f.__iter__
    f.close()
    

    迭代器对象

    只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的。因此我们得找到一个方法能让其他的可迭代对象不依赖索引取值。

    在找到该方法前,首先我们给出迭代器对象的概念:可迭代的对象执行__iter__方法得到的返回值。并且可迭代对象会有一个__next__方法。

    # 不依赖索引的数据类型迭代取值
    dic = {'a': 1, 'b': 2, 'c': 3}
    iter_dic = dic.__iter__()
    print(iter_dic.__next__())
    print(iter_dic.__next__())
    print(iter_dic.__next__())
    # print(iter_dic.__next__())  # StopIteration:
    
    a
    b
    c
    

    img

    for循环原理

    for循环称为迭代器循环,in后必须是可迭代的对象

    is = [1, 2, 3]
    for i in lis:
        print(i)
    

    1
    2
    3

    因为迭代器使用__iter__后还是迭代器本身,因此for循环不用考虑in后的对象是可迭代对象还是迭代器对象。

    由于对可迭代对象使用__iter__方法后变成一个迭代器对象,这个迭代器对象只是占用了一小块内存空间,他只有使用__next__后才会吐出一个一个值。如lis = [1,2,3,4,5,...]相当于一个一个鸡蛋,而lis = [1,2,3,4,5,...].__iter__相当于一只老母鸡,如果你需要蛋,只需要__next__即可。

  • 相关阅读:
    IO模型
    MySQL存储引擎问题
    Flask信号流程
    Flask应用运行流程
    Linux远程连接及常用指令
    Linux的安装与配置
    python GIL锁问题
    python深浅拷贝问题
    pyhton中的__new__和__init__
    直流调速系统Modelica基本模型
  • 原文地址:https://www.cnblogs.com/leaf-wind/p/11340330.html
Copyright © 2011-2022 走看看