python装饰器

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> python装饰器

点击上方”python宝典”,关注获取python全套视频,

技术文章第一时间送达!

装饰器

你是一家互联网公司的后端攻城狮,你们公司有一个现有函数如下:


import time
def add(x,y):
    print(x + y)
    time.sleep(5)
#add(5,9)

现在TEAM LEADER要让你对函数进行扩展,要求在函数执行之前打印时间,执行之后打印时间,你可能很快就完成了任务,代码如下:


import time
def add(x,y):
    print(time.time())
    print(x + y)
    time.sleep(5)
    print(time.time())
add(5,9)

此时你信心满满的把这个代码提交给你的TEAM LEADER审核,没成想,没过5分钟,代码就被打回来了, TEAM LEADER给你反馈是,我现在有很多函数需要加这个功能,你的代码虽然实现了功能,但是需要更改各个函数的代码,这直接违反了软件开发中的一个原则“开放-封闭”原则,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

封闭:已实现的功能代码块不应该被修改

开放:对现有功能的扩展开放

BUT ANYWAY,老大要求的这个怎么实现呢?如何在不改原有功能代码的情况下

加上认证功能呢?我们之前说过高阶函数,就是把一个函数当做一个参数传给另外一个函数,下面就用高阶函数来实现它


<strong>import time
def add(x,y):
    print(x + y)
    time.sleep(5)

定义一个函数
def show_time(f):
    def inner(x,y):#***********这里的参数对应函数f的参数
        print(time.time())
        f(x,y)
        print(time.time())
    return inner

则执行show_time(add)返回一个函数对象inner
print(show_time(add))#function show_time.locals.inner at 0x0000000001F00268

函数对象加括号就会执行函数,则
我们将show_time(add)返回的值赋给一个变量add
add = show_time(add)
再执行add,就实现功能了
add(1,2)</strong>

这样我们在没有修改原函数的前提下,实现了这个功能,此时不管什么函数需要这个功能,你只要:函数名 =  show_time(函数名)  ,然后执行这个函数就可以了,为了代码更加简洁,我们采用注解的方式代替  函数名 =  show_time(函数名),只需要在添加功能的函数上方加一行注解:


import time
def show_time(f):
    def inner(x,y):#***********这里的参数对应函数的参数
        print(time.time())
        f(x,y)
        print(time.time())
    return inner

@show_time 
def add(x,y):
    print(x + y)
    time.sleep(5)
    
add(5,9)

@show_time 就相当于  add = show_time(add),@show_time 就是一个装饰器。

装饰器有参数的情况


import time
def logger(flag):#这里参数控制是否打印时间
    def show_time(f):#这里参数对应函数
        def inner(*x, **y):  # ***********这里的参数对应函数的参数
            start = time.time()
            f(*x, **y)
            end = time.time()
            if flag == True:
                print(end - start)
        return inner
    return show_time
@logger(True)
def add1(*x,**y):
    sum = 0
    for i in x:
        sum += i
    print(sum)
    time.sleep(4)
add1(1,2,3,4,5,6)

分析:执行 logger(True)返回show_time

所以  @logger(True)  相当于  @show_time,只是多加了一个条件,让使用变得更加灵活。

深浅拷贝

浅拷贝 copy(只拷贝第一层,里面层仍指向原来的对象)


s = [[1, 2], 'aaa', 'bbb']
s2 = s.copy() #第一层的数据都拷贝一份
s2[0][0] =888 #修改后s[0][0]也会变,他们指向同一个对象
s2[1] = 'www' #修改后s[1]不会变,各有各的对象
print(s2) #[[888, 2], 'www', 'bbb']
print(s) #[[888, 2], 'aaa', 'bbb']

深拷贝

需要引入copy模块


import copy
s = [[1, 2], 'aaa', 'bbb']
s3=copy.deepcopy(s) #所有层都复制一份,各是各的,互不影响。
s3[0][1] = 666
print(s3) #[[1, 666], 'aaa', 'bbb']
print(s) #[[1, 2], 'aaa', 'bbb']

** **

python装饰器

识别图中二维码,欢迎关注python宝典

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> python装饰器


  转载请注明: 好好学java python装饰器

 上一篇
python生成器&迭代器 python生成器&迭代器
点击上方”python宝典”,关注获取python全套视频, 技术文章第一时间送达! 列表生成式 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 里每个值都加一 普通做法 a = [0, 1, 2, 3, 4, 5, 6,
2021-04-05
下一篇 
python模块学习(一) python模块学习(一)
点击上方”python宝典”,关注获取python全套视频, 技术文章第一时间送达! 模块,用一砣代码实现了某个功能的代码集合。  类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的
2021-04-05