情景介绍

一天,在你正在努力加班的时候,老板给交给你了一个任务,就是在这段代码里将所有函数开始输出一个‘hello’最后输出当前时间,再输出一个“end”,这段代码里包含了大量的函数,你会怎么做?

def f1():
print('proces a') def f2():
print('proces b') def f3():
print('proces c') def f4():
print('proces d') ...
...

刚拿到这个任务,我们可能想着这样做,在每个函数中添加相应的输出语句,这样就能完成任务。

import datetime

def f1():
print('hello')
print('proces a')
print('datetime.datetime.now()')
print('end')
  
def f2():
print('hello')
print('proces b')
print('datetime.datetime.now()')
print('end') def f3():
print('hello')
print('proces c')
print('datetime.datetime.now()')
print('end') def f4():
print('hello')
print('proces d')
print('datetime.datetime.now()')
print('end')
...
...

到我们进行实施的时候我们发现这样写,太麻烦,每一个函数最后都要添加一遍,于是,我们就想到了另一个方法,就是写一个函数,添加在每个函数中。

import datetime

def hel():
print('hello')
print(datetime.datetime.now())
print('end') def f1():
print('hello')
print('proces a')
hel() def f2():
print('hello')
print('proces b')
hel() def f3():
print('hello')
print('proces c')
hel() def f4():
print('hello')
print('proces d')
hel() ...
...

但是我们发现在开始输出的hello还是要添加在每个函数中,这样还是麻烦,为了解决这个问题就要讲讲装饰器了。

装饰器介绍

  装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

简单装饰器

  就将开始那个问题来使用装饰器解决一下。

import datetime

def hel(func):
def inner():
print('hello')
r = func()
print(datetime.datetime.now())
print('end')
return r
return inner @hel
def f1():
print('proces a') @hel
def f2():
print('proces b') @hel
def f3():
print('proces c') @hel
def f4():
print('proces d') f1()
f2()
f3()
f4() 执行结果:
hello
proces a
2018-06-24 18:03:21.903651
end
hello
proces b
2018-06-24 18:03:21.915651
end
hello
proces c
2018-06-24 18:03:21.915651
end
hello
proces d
2018-06-24 18:03:21.915651
end

是不是使用装饰器相对于之前的写法简单。

针对上面的代码进行解析:

  装饰器符号“@”属于语法糖,@修饰符必须出现在函数定义前一行,将下面的函数的名作为参数,不允许和函数定义在同一行。

  在上面的代码中,func就是指f1、f2、f3、f4函数,以f1为例,将f1函数作为参数传入hel函数中,在hel函数中再定义一个inner()函数,在inner函数中,首先执行一个print('hello'),在执行f1函数兵将返回值赋值给r,接下来输出时间以及end,最后返回r,inner函数的最后返回inner函数,当我们执行f1函数的时候,就相当于执行了inner函数,并且可以可以拿到f1函数的返回值。

使用装饰器传递参数

  上面使用的装饰器中,传入的函数没有带参数,当需要修饰的函数带有参数,我们就在装饰器中的inner函数添加相应的参数,在inner函数里面调用func函数的时候,再次传入。

def hel(func):
def inner(name):
r = func(name)
print('bye')
return r
return inner @hel
def f1(name):
print('hello')
print(name) name = 'alexsel'
f1(name) 输出结果:
hello
alexsel
bye

虽然这样我们就解决了参数的问题,但是我们这次传入的参数仅仅是字符串,如果是更加复杂的参数怎么办,这时候我们可以使用我们之前学习函数时候用到的一些可以接收多种类型的参数,*args,**kwargs,使用这两个参数之后我们可以接收任何类型的参数。

def hel(func):
def inner(*args,**kwargs):
r = func(*args,**kwargs)
print('bye')
return r
return inner @hel
def f1(name):
print('hello')
print(name) name = 'alexsel'
f1(name) 输出结果:
hello
alexsel
bye

到这里,简单的装饰器就讲完了,装饰器还有更高级的用法,下一篇,装饰器二会继续给大家讲解装饰器。

Python学习:10.Python装饰器讲解(一)的更多相关文章

  1. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  2. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  3. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  4. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  5. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  6. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  7. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

  8. Python学习系列之装饰器

    装饰器的作用 装饰器用于装饰某个函数.方法或者类,它可以让这个函数执行之前或者执行之后做一些操作 手工实现一个装饰器 def outer(some_func): #装饰器 $1 def inner() ...

  9. Python学习日记(九) 装饰器函数

    1.import time a.time.time() 获取到当前的时间,返回值为浮点型 import time print(time.time()) #1565422783.6497557 b.ti ...

  10. Python 学习 —— 进阶篇(装饰器、类的特殊方法)

    Python基础部分学完之后,在进入其OOP部分前,先理解一下其装饰器这种结构,其功能可类比于Java中的面向切面编程,下面参见具体实例: def log(f): def fn(x): print ' ...

随机推荐

  1. 【Leetcode】【Medium】Path Sum II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  2. Node Sass could not find a binding for your current environment

    Node环境从8升级到10后,Node Sass could not find a binding for your current environment 标签(空格分隔): Node Node环境 ...

  3. Redhat5.9安装qt5.5.1出错error while loading shared libraries:libX11-cxb.so.1 标签: qt5 2017-06-02 11

    出错原因是缺少了共享库libX11-cxb.so.1,是由于系统版本过低所致:重新安装红帽6.5即可解决该问题.

  4. July 09th 2017 Week 28th Sunday

    He that boasts of his own knowledge proclaims ignorance. 夸耀知识实乃无知. Honestly speaking, I don't agree ...

  5. sqoop部署与使用

    sqoop安装 1.下载并解压 scp sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz mini1:/root/apps/ tar -zxvf sqoop-1.4 ...

  6. XAMPP中Apache因为端口原因不能启动的解决方法

    在开启XAMPP的Apache时报出如下错误信息: 9:08:14 PM [Apache] Error: Apache shutdown unexpectedly.9:08:14 PM [Apache ...

  7. poj 3253 Fence Repair (STL优先队列)

    版权声明:本文为博主原创文章,未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/34805369 转载请注明出 ...

  8. 2014年百度之星资格赛第一题Energy Conversion

    Problem Description 魔法师百小度也有遇到难题的时候-- 如今.百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这样的魔法文字须要耗费大量的能量和大量的脑力. 过了许久 ...

  9. v-bind:的基本用法

    1. v-bind:class(根据需求进行选择) <style> .box{ background-color: #ff0; } .textColor{ color: #000; } . ...

  10. es6之proxy和reflect

    一.proxy //Proxy和Reflect //供应商 let obj={ time:"2017-11-21", name:"net", _r:123 } ...