情景介绍

一天,在你正在努力加班的时候,老板给交给你了一个任务,就是在这段代码里将所有函数开始输出一个‘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. 关于windows server 里Let's Encrypt续订的问题

    引言 Let's Encrypt是什么就不详细说了,它是免费的https证书,优点就是免费,缺点就是每三个月就要自己续上.今天主要介绍的是续上有效期的环节. 1.安装certify 下载地址: htt ...

  2. 【Leetcode】【Medium】Multiply Strings

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  3. UIScrollView中的手势

    UIScrollView中的手势 UIScrollView自带了两个手势,分别为: UIPanGestureRecognizer UIPinchGestureRecognizer 他们都是readon ...

  4. ipsec验证xl2tpd报错:handle_packet: bad control packet!

    使用ipsec和xl2tpd搭建好vpn后,使用ipsec密钥方式不能连接,显示 “连接的时候被远程服务器中止” 使用xl2tpd -D查看连接情况,尝试连接了许多次,错误如下: 开始不确定问题所在, ...

  5. selenium+python 数据驱动-txt篇

    #循环读取txt文件中的数据,可以作为用户名,密码等使用from selenium import webdriver #创建两个列表user=[]pwd=[]f=open(r'C:\bbs\data\ ...

  6. .net mvc 路由

    Asp.net Mvc之Action如何传多个参数 在Global.asax文件中,默认路由如下. routes.MapRoute( "Default", // 路由名称 &quo ...

  7. 面试准备——(二)专业知识(4)C/C++语言

    1. 预处理 断言 assert的功能,assert(statement),如果statement为真则程序继续执行,为假则整个程序中断退出 3. #define [ #ifndef DISKSIM_ ...

  8. HDU 1009 FatMouse' Trade(简单贪心)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1009 FatMouse' Trade Time Limit: 2000/1000 MS (Java/O ...

  9. CodeForces - 616C(很有意思的bfs,set,map的使用)

    传送门: http://codeforces.com/problemset/problem/616/C C. The Labyrinth time limit per test 1 second me ...

  10. Java 分支结构

    Java 分支结构 - if...else/switch 顺序结构只能顺序执行,不能进行判断和选择,因此需要分支结构. Java 有两种分支结构: if 语句 switch 语句 if 语句 一个 i ...