• 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)
  • 相关阅读:
    拼音输入法的数学原理
    搜索核心原理之网页和查询的相关性——TF-IDF
    Linux内核源码分析之调度、内核线程模型 And Centos7.2's Kernel Resource Analysis
    手把手教您定制化Centos6.x安装界面
    定制Centos系统(基于6.x)
    数据分析、数据挖掘之聚类、分类
    数据分析、数据挖掘之文档过滤、垃圾邮件
    数据分析、数据挖掘之特征分解、特征分析
    数据挖掘、数据分析之协同过滤、推荐系统、关联分析
    转载-“一代宗师”周金涛先生20个预言待验证
  • 原文地址:https://www.cnblogs.com/wddxx/p/13668107.html
Copyright © 2020-2023  润新知