码迷,mamicode.com
首页 > 编程语言 > 详细

python装饰器

时间:2018-05-17 13:32:46      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:print   复制   tar   python装饰器   很多   logger   完成   lag   灵活   

装饰器

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

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,老大要求的这个怎么实现呢?如何在不改原有功能代码的情况下

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

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)

 

这样我们在没有修改原函数的前提下,实现了这个功能,此时不管什么函数需要这个功能,你只要:函数名 =  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装饰器

标签:print   复制   tar   python装饰器   很多   logger   完成   lag   灵活   

原文地址:https://www.cnblogs.com/IT-Scavenger/p/9045034.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!