zoukankan      html  css  js  c++  java
  • python三大器

    一、装饰器

    器:工具
    装饰:为被装饰对象添加新功能

    装饰器:装饰的工具

    被装饰对象--->>需要添加功能 的函数
    装饰器--->>函数

    装饰器的作用:在不修改被装饰对象源代码与调用方式的前提下,为其加上新的功能
    装饰器必须要遵循的原则:开放封闭原则

    为什么要使用装饰器:可以解决代码冗余问题,提高代码的可扩展性

    开放封闭原则

    开放:对函数功能的添加是开放的。
    封闭:对函数功能修改是封闭的。

    总结原则如下:

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

    目的:在遵循1和2原则的基础上扩展新功能

    模拟下载电影函数的运行时间
    
    import time
    def download_m():
        print('开始下载电影....')
        time.sleep(3)
        print('电影下载完成....')
    #
    # start_time = time.time()
    # download_m()
    # end_time = time.time()
    # print(f'消耗时间:{end_time-start_time}')
    
    
    def time_record():
        def inner():
            start_time = time.time()   #统计开始
            download_m()   #写死了,只能给download_m函数用
            end_time = time.time()
            print(f'消耗时间:{end_time-start_time}')   #结束统计,打印消耗时间
        return inner
    func = time_record()    #返回的是inner的内存地址
    func()    #调用的实质其实是inner函数
    改进版
    import time
    def download_m():
        print('开始下载电影....')
        time.sleep(3)
        print('电影下载完成....')
    
    # 添加时间功能
    def time_record(func):    # func = download_m
        def inner():
            start_time = time.time()   #统计开始
           # download_m()   #写死了,只能给download_m函数用
            func()      # func() = download_m()
            end_time = time.time()
            print(f'消耗时间:{end_time-start_time}')   #结束统计,打印消耗时间
        return inner     #返回的是inner的内存地址
    res = time_record(download_m)  #被装饰对象的调用方式
    res()
    问题1:被装饰对象,有返回值
    
    def download_m():
        print('开始下载电影....')
        time.sleep(3)
        print('电影下载完成....')
        return "小丑.mp4"
    
    def time_record(func):
        def inner():
            start_time = time.time()
            res = func()        # func() = download_m()
            end_time = time.time()
            print(f'消耗时间:{end_time-start_time}')
            return res       #res = download_m()
        return inner
    
    download_m = time_record(download_m)   #  time_record(download_m)=inner#重新赋值给download_m
    download_m()
    问题2:被装饰对象,有参数
    
    def download_m(url):
        print(f'{url}开始下载电影....')
        time.sleep(3)
        print('电影下载完成....')
        return"小泽.mp4"
    
    def time_record(func):  # func <-- download_movie
        # url = 'https://www.baidu.com/'
        # 在闭包函数中
        def inner(url):
            start_time = time.time()
            res = func(url)  # func(url) ---> download_movie(url)
            end_time = time.time()
            print(f'消耗时间: {end_time - start_time}')
            return res
        return inner
    download_m = time_record(download_m)
    download_m('https://www.baidu.com')
    问题3: 假如被装饰对象需要接收多个参数
    
    def download_movie(url1,url2):
        print(f'{url1,url2}开始下载电影....')
        time.sleep(3)  # 等待3秒
        print('电影下载成功...')
        return '小泽.mp4'
    #装饰器最终版本
    def time_record(func):
        def inner(*args,**kwargs):    #*args,**kwargs接受所有的参数
            start_time = time.time()
            res = func(*args,**kwargs)  # 将被装饰对象需要接收的任意参数 原封不动传给func
            end_time = time.time()
            print(f'消耗时间: {end_time - start_time}')
            return res
        return inner
    download_movie = time_record(download_movie)
    download_movie(url1='https://www.baidu.com', url2='https://www.hao123.com')

    叠加装饰器

    叠加装饰器:
        在同一个被装饰对象中,添加多个装饰器,并执行。
        @装饰1
        @装饰2
        @装饰3
        def 被装饰对象():
            pass
    
        注意: 装饰器在调用被装饰对象时才会执行添加的功能。
    
        - 叠加装饰器:
            - 装饰的顺序: 由下到上装饰         
            - 执行的顺序: 由上往下
    
     注意: 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象” func(*args, **kwargs)
        装饰器可以理解在外面套了一层函数,内部定义函数,外层函数返回内层函数的名称
        形式:@+函数名a即可 相当于func=a(func)=inner,func是被装饰函数,理解为修改了函数名。类装饰器表示修改了类名
    def w2(f):
    def inner():
    print('w2')
    res=f()
    print('w2end')
    return res
    return inner
    def wrappers(f):
    #print('h')
    def inner():
    print('1')
    res=f()
    print('2')
    return res
    return inner
    @w2
    @wrappers
    def aaa():
    print('aaa')
    if __name__=='__main__':

    aaa()
    输出结果:

    w2
    1
    aaa
    2
    w2end

    无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
    有参装饰器: 本质上就是在无参装饰器上套了一个外层函数,无参装饰器可以引用外层函数的名字。

    装饰器模板

    def wrapper(func):
        def inner(*args, **kwargs):
        
            为被装饰对象添加新功能
            
            res = func(*args, **kwargs)  # 调用被装饰对象,得到返回值
            
            为被装饰对象添加新功能
            
            return res    
        return inner
    
    def func1():
        pass
    
    func1 = wrapper(func1)
    func1()  # inner()

    装饰器的语法糖

    装饰器语法糖,是属于装饰器的。

    @:装饰器的的语法糖
    注意: 在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上。

    import time
    
    # 统计函数执行时间装饰器
    
    def wrapper(func):  # 被装饰对象
        def inner(*args, **kwargs):  # 被装饰对象的参数
            start_time = time.time()          # 调用前增加新功能
            res = func(*args, **kwargs)         # 调用被装饰对象,并接收返回值
            end_time = time.time()           # 调用后添加新功能
            print(end_time - start_time)
    
            return res
        return inner
        
    @wrapper  # download= wrapper(download_m) 下面相当于没有了
    def download_m()
         print('开始下载电影....')
         time.sleep(3)
         print('电影下载完成....')
    download_m()

    ------------ 这不是装饰器叠加--------------------------
    user,passwd='alex','123'
    #def login_flag(flag=False):
    flag=False #login_state=Flase
    home_login_flag="jingdong" #home的登录状态 应该是从其他地方传过来的参数

    def login_type(auth_type):
    def login(f):
    def inner():
    global flag
    f()
    if home_login_flag==auth_type:
    if flag==False: #if flag:
    username=input("username")
    password=(input('passwd:'))
    if user==username and passwd==password:
    flag=True
    print("wlecom")
    else:
    pass
    else:
    print('denglucuowu')
    return inner
    return login
    @login_type('jingdong') #authentication 认证 auth_type 验证种类 先执行login_type()函数
    def home():
    print("welcom to home page")
    @login_type("weixing")
    def finance():
    print("welcom to finance page")
    @login_type("")
    def book():
    print("welcom to book page")
    # home()
    # finance()
    # book()
     

    定义:

    可迭代对象(Iterable)

    Python中任意的对象, 只要它定义了可以返回⼀个迭代器的__iter__⽅法, 或者定义了可以⽀持下标索引的__getitem__⽅法(这些双下划线⽅法会在其他章节中全⾯解释),那么它就是⼀个可迭代对象。 简单说, 可迭代对象就是能提供迭代器的任意对象

    迭代器(Iterator)
    任意对象, 只要定义了next(Python2) 或者__next__⽅法, 它就是⼀个迭代器。

    ⽣成器(Generators)
    ⽣成器也是⼀种迭代器, 但是你只能对其迭代⼀次。 这是因为它们并没有把所有的值存在
    内存中, ⽽是在运⾏时⽣成值。 你通过遍历来使⽤它们, 要么⽤⼀个“for”循环, 要么将它
    们传递给任意可以进⾏迭代的函数和结构。 ⼤多数时候⽣成器是以函数来实现的。 然⽽,
    它们并不返回⼀个值, ⽽是yield(暂且译作⽣出”)⼀个值。

    二、迭代器

    定义:迭代取值的工具, 它可以迭代取值。
    迭代:是指重复迭代,每一次迭代的结果都是基于上一次的结果而来的
    -可迭代对象:所有序列类型:list、tuple、dict、str、set、f(文件)

    #依赖于索引取值
    goods=['mac','lenovo','acer','dell','sony']
    
    index=0
    while index < len(goods):
        print(goods[index])
        index+=1
    dict1 = {'name':'bob','age':18,'sex':'male'}
    iter_dict1 = dict1.__iter__()    #iter_dict1是一个迭代器对象 
    print(iter_dict1.__next__())
    print(iter_dict1.__next__())
    print(iter_dict1.__next__())
    >>>name
    >>>age
    >>>male
    补充:
    list1 = ['tank', 'jason鸡哥', 'sean', '饼哥']
    iter_list1 = list1.__iter__()
    while True:
        # 补充: try:获取异常
        try:
            print(iter_list1.__next__())   #报错
        #立即触发此代码 StopIteration
        except StopIteration:
            break
    凡是内部有.__iter__()方法的都是可迭代对象。
    
    例如:
    str='hello'
    str1.__iter__()
    
    -获取迭代器:
        通过可迭代对象.__iter__(),得到的返回值就是"迭代器对象
    
    -如何迭代取值:
        迭代器对象.__next__(),每次执行,都会从迭代器对象中取出一个值
        
    -迭代器对象的优点:
         1. 不依赖于索引迭代取值
         2. 节省内存空间。
     缺点:
         1.取指定某个值麻烦
         2.每次取值都要从第一个值开始,无法同过索引取值
         3.无法通过len()计算长度
    
    
            - 迭代器本质上是一个可迭代对象
    
            - 文件本质上既是迭代器对象,也是可迭代对象。
    
            - 可迭代对象不一定是迭代器对象
    
    
    for循环原理:
    
    for i in 可迭代对象:
        - in: 会将可迭代对象自动调用.__iter__()变成迭代器对象
         
        - for循环内置捕获异常机制
    set1 = '1, 2, 3, 4'
    iter_set1 = set1.__iter__()    #iter_set1 迭代器
    print(iter_set1.__iter__() is iter_set1)  #True
    
    list1 = [1, 2, 3, 4]
    iter_list1 = list1.__iter__()
    print(iter_list1 is list1)   #False

    三、生成器

    但凡在函数内部包含关键字yield,调用函数时,函数体代码不会执行,但会返回一个结果,该结果就是一个生成器

    -yield:
        只能在函数内部定义
        每次yield都会往生成器对象中添加一个值,
        yield可以保存函数的暂停状态
    
    
    yield与return:
        相同点:
            返回值的个数都是无限制的。
    
        不同点:
            return只能返回一次值,yield可以返回多次值
    # 自定义的迭代器:
    def func():
        print('form func')
        yield 1
    res = func()  #res是一个生成器
    print(res)  #<generator object func at 0x0000016D5A0DEF48>
    
    
    #当我们通过.__next__取值时,才会执行函数体代码。
    def func():
        print('from func')
        yield 1
    res = func()
    print(res.__next__())
    
    
    def func():
        print('开始准备下蛋')
        print('一个鸡蛋')
        yield '鸡蛋1'
        print('第二个鸡蛋')
        yield '鸡蛋2'
        print('第三个鸡蛋')
        yield '鸡蛋3'
        print('取最后一个鸡蛋,查看是否还有')
    res = func()   #res是迭代器对象
    # print(next(res))
    # print(next(res))
    # print(next(res))
    # print(next(res)) #StopIteration 报错
    
    迭代器对象.__next__() ==next(迭代器对象)
    print(res.__next__())   #当我们通过.__next__取值时,才会执行函数体代码
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())   #StopIteration 报错
    
    # 循环10次
    for i in range(1,11):
        print(i)
      #  python2:range(1,5)--->[1,2,3,4]
      # python3:range(1,5) --->range对象 --->生成器 --->迭代器
    
    #自定义range功能,创建一个自定义的生成器
    def my_range(start,end,move):
        while start<end:
            yield start
            start +=move
    
    g_range = my_range(1,5,2)   #g_range 是生成器
    print(g_range)
  • 相关阅读:
    9.11 eventbus
    9.10,,,实现new instanceof apply call 高阶函数,偏函数,柯里化
    9.9 promise实现 写完了传到gitee上面了,这里这个不完整
    9.5cors配置代码
    9.5 jsonp 实现
    9.5 http tcp https总结
    9.3 es6 class一部分 and es5 class 发布订阅
    8.30 cookie session token jwt
    8.30vue响应式原理
    warning: LF will be replaced by CRLF in renard-wx/project.config.json. The file will have its original line endings in your working directory
  • 原文地址:https://www.cnblogs.com/wddxx/p/13668107.html
Copyright © 2011-2022 走看看