详解Python装饰器 给你的咖啡加点料

一、函数回顾

1、在python中函数是一等公民,函数也是对象。我们可以把函数赋予变量。

def make_cofe(type):
    print('获得一杯 : {}'.format(type))
​
get_cofe = make_cofe
get_cofe('咖啡')
​
####输出#####
获得一杯 : 咖啡

这个例子中,我们把函数make_cofe 赋予了变量 get_cofe,这样之后你调用 get_cofe,就相当于是调用函数 make_cofe()。

2、把函数当作参数,传入另一个函数中。

def make_cofe(type):
    print('获得一杯 : {}'.format(type))
​
def shop(func,type):
    func(type)
​
shop(make_cofe,'咖啡')
​
####输出####
获得一杯 : 咖啡

这个例子,我们把make_cofe以参数的形式传入shop中,然后调用它。

3、函数是可以嵌套的。

def shop(type):
    def make_cofe(type):
        print('获得一杯 : {}'.format(type))
    make_cofe(type)
​
shop('咖啡')
​
#####输出####
获得一杯 : 咖啡

这段代码中,我们在函数shop内部定义了函数make_cofe 4、函数的返回值也可以是函数对象(闭包)。

def shop():
    def make_cofe(type):
        print('获得一杯 : {}'.format(type))
    return make_cofe
​
get_cofe=shop()
get_cofe("咖啡")
​
####输出#####
获得一杯 : 咖啡

这里,函数 shop() 的返回值是函数对象 make_cofe 本身,之后,我们将其赋予变量 get_cofe,再调用 get_cofe("咖啡")。

二、装饰器

下面我们正式开始装饰器的学习。 我们先想一个问题。如果我们去咖啡店要一杯咖啡,我们应该如何实现。你也许会这么写。

def cofe():
    print('咖啡', end='')
​
cofe()
​
####输出####
咖啡

那我们现在想来一杯加糖咖啡,我们该如何写呢?你也许会这么想,那还不简单,直接在cofe()函数里改不就好了。

def cofe():
    print('加糖咖啡', end='')
​
cofe()
​
####输出####
加糖咖啡

那么问题来了,如果我们现在不想喝加糖咖啡了,该怎么办呢,总不能在cofe()函数里去掉吧。那如果有人想喝加糖咖啡、有人不想喝加糖咖啡如何是好,总不能写两个cofe()函数吧。 那我们带着问题看一下下面这段代码。

def add_sugar(func):
    def add():
        print('加糖',end='')
        func()
    return add
​
def cofe():
    print('咖啡',end='')
​
cofe = add_sugar(cofe)
​
print("获得一杯",end='')
cofe()
​
####输出#####
获得一杯加糖咖啡

变量 cofe 指向了内部函数 add(),而内部函数 add() 中又会调用原函数 cofe(),因此,最后调用 cofe() 时,就会先打印‘加糖',然后输出‘咖啡'。这里的函数 add_sugar() 就是一个装饰器,它把真正需要执行的函数cofe()包裹在其中,并且改变了它的行为,但是原函数 cofe() 不变。 下面我们来看一下更优雅的写法。

def add_sugar(func):
    def add():
        print('加糖',end='')
        func()
    return add
​
@add_sugar
def cofe():
    print('咖啡',end='')
​
print("获得一杯",end='')
cofe()
​
#####输出#####
获得一杯加糖咖啡

这里的@叫做语法糖, @add_sugar就相当于前面的cofe = add_sugar(cofe)语句,只不过更加简洁。因此程序中建议用这种写法。 好了,让我们来回顾下我们的问题,如果有人想喝加糖咖啡、有人不想喝加糖咖啡如何是好。学了装饰器那不就很简单了,如果要喝加糖咖啡,我们把加糖的装饰器@add_sugar给加上不就好了,如果喝不加糖的,那就不加装饰器,这样我们就把这个问题给完美解决掉了。在不改变函数内部的前提了,给函数又添加了新的功能。 到目前为止,我们已经把最简单的装饰器学完了。下面我们在考虑一个问题,如果原函数 cofe() 中,有参数需要传递给装饰器怎么办?一个简单的办法,是可以在对应的装饰器函数 add() 上,加上相应的参数。

def add_sugar(func):
    def add(type):
        print('加糖',end='')
        func(type)
    return add
​
@add_sugar
def cofe(type):
    print('{}咖啡'.format(type),end='')
​
​
cofe("美式")
print()
cofe("拿铁")
​
####输出#####
加糖美式咖啡
加糖拿铁咖啡

不过,新的问题来了。如果我另外还有一个函数(奶茶函数),也需要使用 add_sugar() 装饰器,但是这个新的函数有两个参数,又该怎么办呢? 通常情况下,我们会把*args和 **kwargs,作为装饰器内部函数 add() 的参数。*args和**kwargs,表示接受任意数量和类型的参数,因此加糖装饰器就可以写成下面的形式:

def add_sugar(func):
    def add(*args, **kwargs):
        print('加糖',end='')
        func(*args, **kwargs)
    return add

@add_sugar
def cofe(type):
    print('{}咖啡'.format(type),end='')
​
@add_sugar
def milk_tea(type,num):
    print('{}杯{}奶茶'.format(num,type), end='')
​
​
cofe("美式")
print()
milk_tea("xx牌子","4")
​
####输出####
加糖美式咖啡
加糖4杯xx牌子奶茶

这样我们的咖啡和奶茶都可以加糖了。 前面我们讲的是函数的装饰器,下面我们来讲一下类作为装饰器。类装饰器主要依赖于函数__call__(),每当你调用一个类的实例时,函数__call__()就会被执行一次。

​class Add_sugar:
    def __init__(self, func):
        self.func = func
        self.add_suger = "加糖"
​
    def __call__(self, *args, **kwargs):
        print(self.add_suger,end='')
        return self.func(*args, **kwargs)
​
@Add_sugar
def cofe():
    print("咖啡")
​
cofe()
​
####输出#####
加糖咖啡

最后如果我们的咖啡既要加糖又要加冰,那我们该如何做呢?我们定义一个加冰的装饰器就好了呀。

def add_sugar(func):
    def add():
        print('加糖',end='')
        func()
    return add
​
def add_ice(func):
    def add():
        print('加冰',end='')
        func()
    return add
​
​
@add_sugar
@add_ice
def cofe():
    print('咖啡',end='')
​
cofe()
​
####输出####
加糖加冰咖啡

到此这篇关于Python装饰器-给你的咖啡加点料的文章就介绍到这了,更多相关Python装饰器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python装饰器限制函数运行时间超时则退出执行

    实际项目中会涉及到需要对有些函数的响应时间做一些限制,如果超时就退出函数的执行,停止等待. 可以利用python中的装饰器实现对函数执行时间的控制. python装饰器简单来说可以在不改变某个函数内部实现和原来调用方式的前提下对该函数增加一些附件的功能,提供了对该函数功能的扩展. 方法一. 使用 signal # coding=utf-8 import signal import time def set_timeout(num, callback): def wrap(func): def h

  • python 一篇文章搞懂装饰器所有用法(建议收藏)

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起.在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,这顶帽子我们称之为装饰函数 或 装饰器. 你要问我装饰器可以实现什么功能?我只能说你的脑洞有多大,装饰器就有多强大. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以

  • python装饰器练习题及答案

    这篇文章主要介绍了python装饰器练习题及答案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一:编写装饰器,为多个函数加上认证的功能(用户的账号密码) 要求登录成功一次,后续的函数都无需输入用户名和密码 FLAG=False#此时还未登录 全局变量 写这个步骤的意义在于:方便 知道已经登录成功了,就不再重复登录 def login(func):#为多个函数加上的认证功能 def inner(*args,**kwargs):#加上装饰器 gl

  • python装饰器简介---这一篇也许就够了(推荐)

    Python装饰器(decorator)是在程序开发中经常使用到的功能,合理使用装饰器,能让我们的程序如虎添翼. 装饰器引入 初期及问题诞生 假如现在在一个公司,有A B C三个业务部门,还有S一个基础服务部门,目前呢,S部门提供了两个函数,供其他部门调用,函数如下: def f1(): print('f1 called') def f2(): print('f2 called') 在初期,其他部门这样调用是没有问题的,随着公司业务的发展,现在S部门需要对函数调用假如权限验证,如果有权限的话,才

  • python使用装饰器作日志处理的方法

    装饰器这东西我看了一会儿才明白,在函数外面套了一层函数,感觉和java里的aop功能很像:写了2个装饰器日志的例子, 第一个是不带参数的装饰器用法示例,功能相当于给函数包了层异常处理,第二个是带参数的装饰器用法示例,将日志输出到文件. ``` #coding=utf8 import traceback import logging from logging.handlers import TimedRotatingFileHandler def logger(func): def inner(*

  • Python类装饰器实现方法详解

    本文实例讲述了Python类装饰器.分享给大家供大家参考,具体如下: 编写类装饰器 类装饰器类似于函数装饰器的概念,但它应用于类,它们可以用于管理类自身,或者用来拦截实例创建调用以管理实例. 单体类 由于类装饰器可以拦截实例创建调用,所以它们可以用来管理一个类的所有实例,或者扩展这些实例的接口. 下面的类装饰器实现了传统的单体编码模式,即最多只有一个类的一个实例存在. instances = {} # 全局变量,管理实例 def getInstance(aClass, *args): if aC

  • python函数装饰器之带参数的函数和带参数的装饰器用法示例

    本文实例讲述了python函数装饰器之带参数的函数和带参数的装饰器用法.分享给大家供大家参考,具体如下: 1. 函数带多个参数 # 普通的装饰器, 打印函数的运行时间 def decrator(func): def wrap(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print('运行时间为', end_time-start_time) return

  • 详解Python装饰器 给你的咖啡加点料

    一.函数回顾 1.在python中函数是一等公民,函数也是对象.我们可以把函数赋予变量. def make_cofe(type): print('获得一杯 : {}'.format(type)) ​ get_cofe = make_cofe get_cofe('咖啡') ​ ####输出##### 获得一杯 : 咖啡 这个例子中,我们把函数make_cofe 赋予了变量 get_cofe,这样之后你调用 get_cofe,就相当于是调用函数 make_cofe(). 2.把函数当作参数,传入另一

  • 实例详解Python装饰器与闭包

    闭包是Python装饰器的基础.要理解闭包,先要了解Python中的变量作用域规则. 变量作用域规则 首先,在函数中是能访问全局变量的: >>> a = 'global var' >>> def foo(): print(a) >>> foo() global var 然后,在一个嵌套函数中,内层函数能够访问在外层函数中定义的局部变量: >>> def foo(): a = 'free var' def bar(): print(a)

  • 详解Python装饰器

    1. 定义 本质是函数,用来装饰其他函数,为其他函数添加附加功能 2. 原则 a. 不能修改被装饰函数的源代码 b. 不能修改被装饰的函数的调用方式 3. 实现装饰器知识储备 a. 函数就是变量 b. 高阶函数     i. 把一个函数当作实参传给另外一个函数,在不修改被装饰函数源代码情况下为其添加功能     ii. 返回值中包含函数名, 不修改函数的调用方式 c. 嵌套函数 高阶函数+嵌套函数==>装饰器 # Author: Lockegogo user, passwd = 'LK', '1

  • 详解Python装饰器的四种定义形式

    目录 前言 用函数装饰函数 用函数装饰一个类 用类定义装饰器,然后装饰一个函数 用类定义装饰器,然后装饰一个类 小结 前言 装饰器(decorator)在Python框架中扮演着重要角色,是Python中实现切面编程(AOP)的重要手段. aspect-oriented programming (AOP) ,在不改变代码自身的前提下增加程序功能 不改变代码自身,但需要在函数和类头上加一个标注(annotation),这个标注在Python里叫装饰器,在java里叫注解.在Python里,一共有四

  • 详解Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

  • 详解Python 装饰器执行顺序迷思

    探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会说明它们是自上而下的,比如下面这个例子: def decorator_a(func): print 'Get in decorator_a' def inner_a(*args, **kwargs): print 'Get in inner_a' return func(*args, **kwarg

  • 详解利用装饰器扩展Python计时器

    目录 介绍 理解 Python 中的装饰器 创建 Python 定时器装饰器 使用 Python 定时器装饰器 Python 计时器代码 其他 Python 定时器函数 使用替代 Python 计时器函数 估计运行时间timeit 使用 Profiler 查找代码中的Bottlenecks 总结 介绍 在本文中,云朵君将和大家一起了解装饰器的工作原理,如何将我们之前定义的定时器类 Timer 扩展为装饰器,以及如何简化计时功能.最后对 Python 定时器系列文章做个小结. 这是我们手把手教你实

  • 详解Python装饰器之@property

    一.property() 函数讲解 了解 @property 装饰器之前,我们首先要了解内置函数的 property(). class property(fget=None, fset=None, fdel=None, doc=None) 描述: 返回 property 属性. 参数说明: fget -- 获取属性值的函数. fset -- 设置属性值的函数. fdel -- 删除属性值函数. doc -- property 属性的文档字符串,如果没有给出 doc,则该 property 将拷贝

  • Python装饰器(decorator)定义与用法详解

    本文实例讲述了Python装饰器(decorator)定义与用法.分享给大家供大家参考,具体如下: 什么是装饰器(decorator) 简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象.所以,我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码.比较常用的场景有日志插入,事务处理等. 装饰器 最简单的函数,返回两个数的和 def calc_add(a, b): return a + b calc_add(1, 2) 但是现在又有新

  • 基于Python 装饰器装饰类中的方法实例

    title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] category: ['Python'] --- 目前在中文网上能搜索到的绝大部分关于装饰器的教程,都在讲如何装饰一个普通的函数.本文介绍如何使用Python的装饰器装饰一个类的方法,同时在装饰器函数中调用类里面的其他方法.本文以捕获一个方法的异常为例来进行说明. 有一个类Test, 它的结构如下: clas

随机推荐