Python基础-----装饰器

一、装饰器定义

  • 器即函数;装饰即修饰,意指为其他函数添加新功能;

  • 装饰器定义:本质就是函数,功能是为其他函数添加新功能

二、装饰器的原则

  • 1.不修改被装饰函数的源代码(开放封闭原则)

  • 2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

三、高阶函数

满足如下条件之一就可称之为高阶函数

  • 1.函数接收的参数是一个函数名
  • 2.函数的返回值是一个函数名

高阶函数总结

  • 1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
  • 2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

四、闭包

  • 闭包:在一个作用域里放入定义变量(或嵌套函数),相当于打了一个包
    想要给内部传入参数,用闭包的话只需要在最外部传入即可
def father(name):
   def son():
        def grandson():
            print('from %s'%name)
        grandson()
   son()

father('Meanwey')

五、装饰器框架实现

import time
def timmer(func):    #func = test
   def wrapper():
      start_time = time.time()
      func()       #执行test函数
      stop_time = time.time()
      print('运行时间%s'%(stop_time - start_time))
   return wrapper

def test():
   time.sleep(3)
   print('函数运行完毕')

test = timmer(test)   #返回的是wrapper的函数地址
test()           #执行wrapper函数,内部再运行test函数

上面代码符合装饰器的基本原则,但是调用test函数之前进行了赋值操作

六、装饰器语法糖

  • @装饰函数 (将该句代码放置于修饰函数前即可)
  • 就上例来讲,@timmer 就相当于 test = timmer(test)
import time
def timmer(func):    #func = test
   def wrapper():
      start_time = time.time()
      func()       #执行test函数
      stop_time = time.time()
      print('运行时间%s'%(stop_time - start_time))
   return wrapper

@timmer   #等同于test = timmer(test)
def test():
   time.sleep(3)
   print('函数运行完毕')

test()

七、加上返回值

import time
def timmer(func):    #func = test
   def wrapper():
      start_time = time.time()
      res = func()       #执行test函数
      stop_time = time.time()
      print('运行时间%s'%(stop_time - start_time))
      return res
   return wrapper

@timmer   #等同于test = timmer(test)
def test():
   time.sleep(3)
   print('函数运行完毕')
   return '这是test的返回值'
a = test()   #实际执行wrapper函数
print(a)

八、加上参数

import time
def timmer(func):    #func = test
   def wrapper(name,age):
      start_time = time.time()
      res = func(name,age)       #执行test函数,参数来自wrapper接收的参数
      stop_time = time.time()
      print('运行时间%s'%(stop_time - start_time))
      return res
   return wrapper

@timmer   #等同于test = timmer(test)
def test(name,age):
   time.sleep(3)
   print('我叫%s,年龄%d'%(name,age))
   return '这是test的返回值'
a = test('alex',18)   #实际执行wrapper函数
但是参数是固定的,不适用于所有函数,则改变如下:
import time
def timmer(func):    #func = test
   def wrapper(*args,**kwargs):        #可以用*  **来传入多参数
      start_time = time.time()
      res = func(*args,**kwargs)       #执行test函数,参数来自wrapper接收的参数
      stop_time = time.time()
      print('运行时间%s'%(stop_time - start_time))
      return res
   return wrapper

@timmer   #等同于test = timmer(test)
def test(name,age):
   time.sleep(3)
   print('我叫%s,年龄%d'%(name,age))
   return '这是test的返回值'

@timmer
def test1(name,age,gender):
   time.sleep(3)
   print('我叫%s,年龄%d,性别%s'%(name,age,gender))
   return '这是test的返回值'
a = test('alex',18)   #实际执行wrapper函数
b = test1('tony',22,'male')   #该处将'tony',22,'male'参数放入*args == *('tony',22,'male')
                              #(一一对应,相当于解压)

九、实例(验证功能装饰器)

user_list = [
         {'name':'a','password':'123'},
         {'name':'b','password':'123'},
         {'name':'c','password':'123'},
         {'name':'d','password':'123'}
]   #所有用户信息列表(值为字符串类型)

current_user = {'username':None,'login':False}    #记录用户当前登录状态

def auth_func(func):
   def wrapper(*args,**kwargs):
      if current_user['username'] and current_user['login']:   #如果已经登录,则无需登陆
         res = func(*args,**kwargs)
         return res
      username = input('用户名:').strip()   #上面if不成立,则登录
      password = input('密码:').strip()
      for user_dic in user_list:    #for遍历的是用户列表的中用户信息字典
         if username == user_dic['name'] and password == user_dic['password']: #登录验证
            current_user['username'] = username   #登录成功,更改用户状态
            current_user['login'] = True
            res = func(*args,**kwargs)
            return res

      print('用户名或密码错误,请重新登录!')
   return wrapper

@auth_func
def home(name):
   print('欢迎 %s 来到主页'%name)

@auth_func
def shopping_car(name):
   print('%s 的购物车里有:学习用品,生活用品!'%name)

home('Jerry')
print(current_user)
shopping_car('Jerry')

基础知识补充

列表解压

  • 如要获取列表的第一个和最后一个值,不用索引来取
 l = [10,2,3,4,5,7,5,4,2,32]
 first_num,*other_num,last_num = l   #  *+变量名   表示中间的所有元素
 print(first_num,last_num)
 print(*other_num)

如需互换两个变量的值

 a = 1
 b = 2
 a,b = b,a
 print(a,b)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 记录自己学习py基础的点点滴滴 装饰器 由浅入深,先定义一个函数,把这个函数赋值给一个变量,然后可以通过变量直接调...
    爱跳的兔子阅读 1,547评论 0 0
  • 在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过...
    愚灬墨阅读 3,233评论 1 1
  • 在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过...
    lijincheng阅读 11,240评论 0 5
  • 转载来自:http://blog.csdn.net/u013471155 在学习Python的过程中,我相信有很多...
    JM68阅读 3,685评论 3 9
  • 愿自己既能活成对爱心存美好的关关,又能过成不怕孤独最强大最酷的安迪。 去年还在长春的时候看了欢乐颂1,最近跟着看了...
    Grieva_阅读 2,844评论 0 1