装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器语法简单,代码可读性高。因此,装饰器在Python项目中有广泛的应用。

装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的函数对象定义有__call__方法)。在Python 2.6以及之后的Python版本中,装饰器被进一步用于加工类。

装饰函数和方法

先定义两个简单的数学函数,一个用来计算平方和,一个用来计算平方差,在拥有了基本的数学功能之后,我们可能想为函数增加其它的功能,比如打印输入。我们可以改写函数来实现这一点:

# get square sum
def square_sum(a, b):
print("intput:", a, b)
return a**2 + b**2 # get square diff
def square_diff(a, b):
print("input", a, b)
return a**2 - b**2 print(square_sum(3, 4))
print(square_diff(3, 4))

现在,我们使用装饰器来实现上述修改:

def decorator(F):#装饰器接收一个可调用对象作为输入参数
def new_F(a, b):
print("input", a, b)#new_F中,我们增加了打印的功能
return F(a, b)#并通过调用F(a, b)来实现原有函数的功能。
return new_F#并返回一个新的可调用对象。装饰器新建了一个可调用对象,也就是new_F。 # get square sum
@decorator
def square_sum(a, b):
return a**2 + b**2 # get square diff
@decorator
def square_diff(a, b):
return a**2 - b**2 print(square_sum(3, 4))
print(square_diff(3, 4))

定义好装饰器后,我们就可以通过@语法使用了。在函数square_sum和square_diff定义之前调用@decorator,我们实际上将square_sum或square_diff传递给decorator,并将decorator返回的新的可调用对象new_F赋给原来的函数名(square_sum或square_diff)这个函数对象

所以,当我们调用square_sum(3, 4)的时候,就相当于:

square_sum = New_F

square_sum(3, 4)

再例:

即@fun_a与声明fun_b = fun_a(fun_b)等价

def fun_a(ob):
print "hello"
print ob.__doc__
return ob @fun_a
def fun_b(a,b):
"""this is function b"""
print a+b
print "world" fun_b(3,4)
----------------------------------
def fun_a(ob):
print "hello"
print ob.__doc__
return ob def fun_b(a,b):
"""this is function b"""
print a+b
print "world" fun_b = fun_a(fun_b) #等价@fun_a
fun_b(3,4)

小结

Python中的变量名和对象是分离的。变量名可以指向任意一个对象。

从本质上,装饰器起到的就是这样一个重新指向变量名的作用(name binding),让同一个变量名指向一个新返回的可调用对象,从而达到修改可调用对象的目的。

如果我们有其他的类似函数,我们可以继续调用decorator来修饰函数,而不用重复修改函数或者增加新的封装。这样,我们就提高了程序的可重复利用性,并增加了程序的可读性。

装饰类

装饰器被拓展到类。一个装饰器可以接收一个类,并返回一个类,从而起到加工类的效果。

def decorator(aClass):
class newClass:
def __init__(self, age):
self.total_display = 0
self.wrapped = aClass(age)
def display(self):
self.total_display += 1
print("total display", self.total_display)
self.wrapped.display()
return newClass
"""在decorator中,我们返回了一个新类newClass。
在新类中,我们记录了原来类生成的对象(self.wrapped),并附加了新的属性total_display,用于记录调用display的次数。我们也同时更改了display方法。"""
@decorator
class Bird:
def __init__(self, age):
self.age = age
def display(self):
print("My age is",self.age) eagleLord = Bird(5)
for i in range(3):
eagleLord.display()

Python Study (05)装饰器的更多相关文章

  1. Python深入05 装饰器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法 ...

  2. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  3. [python基础]关于装饰器

    在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...

  4. python笔记 - day4-之装饰器

                 python笔记 - day4-之装饰器 需求: 给f1~f100增加个log: def outer(): #定义增加的log print("log") ...

  5. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  6. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  7. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  8. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  9. Python进阶之装饰器

    函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用.既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一 ...

  10. Python的property装饰器的基本用法

    Python的@property装饰器用来把一个类的方法变成类的属性调用,然后@property本身又创建了另一个装饰器,用一个方法给属性赋值.下面是在类中使用了@property后,设置类的读写属性 ...

随机推荐

  1. Oracle 11gR2 List-Range分区实验

    一.实验目的 採用List-Range分区,对主分区指定表空间或者对子分区指定表空的不同情况,測试例如以下内容: 1.对List主分区不指定表空间.对Range子分区指定表空间,数据实际存储在哪个表空 ...

  2. java 命令行 编译 运行程序

    学习java使用IDE前最好先用用命令行的javac.java来跑一跑简单的程序,这样能够熟悉一下包管理对.class文件路径的影响. 我们先写一段简单的代码: package com.csdn.lk ...

  3. vs2015编译使用GRPC

    1.获取源码:位于github上 电脑装有git的直接克隆,未装git下载压缩包也可以 git clone  https://github.com/grpc/grpc.git cd grpc git ...

  4. 关于作者&情况

    本校第一次做信奥 , 如有错误, 见谅 本人之前从未接触编程, 选择信奥也只是因为怕被其他奥赛给淘汰... 这应该是懦弱吧...... 但自从接触编程以来, 虽然算不上极大的热爱, 但发自内心地喜欢它 ...

  5. Linux下JDK Tomcat MySQL基本环境搭建

    1. 安装JDK wget http://download.oracle.com/otn-pub/java/jdk/8u181-b13/96a7b8442fe848ef90c96a2fad6ed6d1 ...

  6. POJ 2752 KMP中next数组的应用

    题意: 让你从小到大输出给的字符串中既是前缀又是后缀的子串的长度. 思路: 先要了解这个东西: KMP中next数组表示的含义:记录着字符串匹配过程中失配情况下可以向前多跳几个字符,它描述的也是子串的 ...

  7. A - Presents

    Problem description Little Petya very much likes gifts. Recently he has received a new laptop as a N ...

  8. 3.Ventuz Designer新建项目Demo

    Ventuz Designer新建项目Demo 1.打开ventuz,点Recent Projects>New Project,在弹出的界面填写具体项目信息,如下图: 图1.1 图1.2 2.在 ...

  9. 完美解决ios10及以上Safari无法禁止缩放的问题

    移动端web缩放有两种: 1.双击缩放: 2.双指手势缩放. 在iOS 10以前,iOS和Android都可以通过一行meta标签来禁止页面缩放 <meta content="widt ...

  10. Oracle表的种类及定义

    1表的类型 1)堆组织表(heap organized tables). 当增加数据时,将使用在段中找到的第一个适合数据大小的空闲空间.当数据从表中删除时,留下的空间允许随后的insert和updat ...