Python3--装饰器

原创 2018年04月15日 02:15:13

装饰器

    装饰,顾名思义就是在原来的基础上进行美化及完善,器这里指函数,所以说装饰器就是装饰函数,也就是在不改变原来函数的代码及调用方式的前提下对原函数进行功能上的完善。其核心原理其实是利用闭包

格式 @关键字+装饰函数
         被装饰函数() 
    注意:@行必须顶头写而且是在被装饰函数的正上方

    按照形式可以分为:无参装饰器和有参装饰器,有参装饰器即给装饰器加上参数

引入:想要在原来的函数里增加新的功能,需要用到嵌套函数

想要在nanbei这个函数里增加新的功能,可以再次定义一个函数boom,这样修改了原来的代码,会增加出错的概率,那怎么办呢?

可以在外面动态修改结果:

def nanbei():
    return '南北,'  #原函数

def boom():
    return nanbei() + '你真是一位好老师哦~'

print(boom())

#运行结果:
南北,你真是一位好老师哦~

但希望还是使用nanbei()这个函数名,不用boom()

def nanbei():
    return '南北,'  #原函数

def boom(func):#括号里传入的是nanbei()这个函数
        return func() + '你真是一位好老师哦~'
    
nanbei = boom(nanbei) 
print(nanbei)

#运行结果:
南北,你真是一位好老师哦~

但是还是不太一样,本来应该是print(nanbei()),现在是print(nanbei),继续:

def nanbei():
    return '南北,'  #原函数

def boom(func):#括号里传入的是nanbei()这个函数
    def new_func():
        return func() + '你真是个好老师哦~'
    return new_func
nanbei = boom(nanbei) 
print(nanbei())

#运行结果:
南北,你真是个好老师哦~

上面的boom就是一个装饰器

以上是装饰器的原理

下面是装饰器的用法:

def boom(func):
    def new_func():
        return func() + '你真是个好老师哦~'
    return new_func

@boom #相当于 nanbei = boom(nanbei),如果不用@boom,就要在函数后面写nanbei = boom(nanbei)

def nanbei():
    return '南北,'  #原函数
 
print(nanbei())

@符号是装饰器的语法糖,在定义函数的时候使用

注意: 时刻牢记 @boom只是一个语法糖,其本质是nanbei = boom(nanbei)

其他装饰器:

(1)@property:像访问属性一样访问方法

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

# 像访问属性一样访问方法
    @property
    def get_area(self):
        return self.width *self.length

rec1= Rectangle(50,30)
print(rec1.get_area)#不加@property装饰器,调用方法的时候需要加括号,即print(rec1.get_area())

(2)@staticmethod:静态方法

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        
    def fun1():
        print('我没有self')
    
Rectangle.fun1()

这样看上去没有什么问题,也能运行,但其实这段代码在pycharm中会有波浪线提示,有瑕疵。这时就需要加上@staticmethod这个装饰器,表明fun1这个函数和我们的类没有多大关系

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        
    @staticmethod  
    def fun1():
        print('我没有self')
    
Rectangle.fun1()

(3)@classmethod:类装饰器

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        
    @classmethod
    def show(cls): #cls代表类本身 如果加上self在调用时要把实例传入
        print(cls)
        print('show fun')
    
Rectangle.show()

#运行结果:
<class '__main__.Rectangle'>
show fun
注:@staticmethod不能访问类属性和类方法,@classmethod可以访问类属性    但都可以用类名访问
class Rectangle(object):
    
    name= '我是一个长方形' #定义一个类变量
    
    def __init__(self, length, width):
        self.length = length
        self.width = width
    
    @staticmethod  
    def fun1():
        #print(name) #会报错,@staticmethod不能访问类属性和类方法  
        print('我没有self')
        
    @classmethod
    def show(cls): #cls代表类本身 如果加上self在调用时要把实例传入
        print(cls)
        print(cls.name)
        print('show fun')
    
#Rectangle.fun1() #会报错,@staticmethod不能访问类属性和类方法
Rectangle.show()

#运行结果:
<class '__main__.Rectangle'>
我是一个长方形
show fun

类装饰器:类可以做装饰器,但必须定义__call__方法

class TestClass(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('1234')
        return self.func()

@TestClass
def shuzi():
    print('5678')

shuzi()

# 运行结果
1234
5678

装饰器参考:

from datetime import datetime

def run_time(func):
    def new_func(*args,**kwargs):
        start_time = datetime.now()
        print('程序开始时间:%s' % start_time)
        func(*args, **kwargs)
        end_time = datetime.now()
        print('程序结束时间:%s' % end_time)
        print('程序总共执行时间:%s' % (end_time - start_time))

    return new_func()

练习:

测试type和isinstance两个函数,那个速度更加的快

from datetime import datetime
from time import sleep

def run_time(func):
    def new_func(*args,**kwargs):
        start_time = datetime.now()
        print('程序开始时间;%s' % start_time)
        a = func(*args,**kwargs)
        end_time = datetime.now()
        print('程序结束时间:%s' % end_time)
        print('程序总共执行时间:%s'% (end_time - start_time))
        return a
    return new_func

@run_time
def test_time1(*args):
    return type(*args)

print(test_time1('啊哈哈哈'))

sleep(2)
print('')

@run_time
def test_time2(*args):
    
    return isinstance(*args,str)

print(test_time2('kmkl'))

#运行结果:
程序开始时间;2018-04-15 02:12:37.799030
程序结束时间:2018-04-15 02:12:37.817031
程序总共执行时间:0:00:00.018001
<class 'str'>

程序开始时间;2018-04-15 02:12:39.870149
程序结束时间:2018-04-15 02:12:39.879149
程序总共执行时间:0:00:00.009000
True
由此可见,isinstance的效率比type的效率高








QQ空间装饰器QQ空间装饰器QQ空间装饰器QQ空间装饰器QQ空间装饰器

  • 2009年06月10日 01:33
  • 1.26MB
  • 下载

angular2.0装饰器祥解

@SkipSelf装饰器 在注入器injector层级中的祖先injector中查找 CoreModule,如果没有祖先injector则会提供一个CoreModule实例...
  • u010977147
  • u010977147
  • 2016-12-15 10:43:03
  • 4906

如何去理解闭包&装饰器

首先从概念上看“在python中, 函数本身也是对象” 1.python中一切皆对象 当执行: alist = [1, 2, 3] 时,你就创建了一个列表对象,并且用alist...
  • yongsan01
  • yongsan01
  • 2016-07-27 23:14:39
  • 842

9-5在类中定义装饰器

# -*- coding:utf-8 -*-""" 实际案例: 实现一个能将函数调用信息记录到日志的装饰器: 1.把每次函数的调用时间,执行时间.调用次数写入日志. 2.可以对被装饰函数分组,调用信息...
  • xiaochonghao
  • xiaochonghao
  • 2017-03-24 09:54:26
  • 684

Python实战小程序——装饰器

第四题:简述对Python装饰器的理解,写一个简单的装饰器。 要理解装饰器,我们先介绍一下几点python的基础知识。 1、作用域(命名空间)及变量生存周期 有过一点编程基础的都知道namesp...
  • misayaaaaa
  • misayaaaaa
  • 2016-11-04 16:15:29
  • 978

es7装饰器小入门

es7 装饰器 简单梳理安装npm i babel-plugin-transform-decorators-legacy babel-register --save-dev 安装: babel-plu...
  • qq_26383604
  • qq_26383604
  • 2018-01-14 23:09:54
  • 421

深入理解Python 装饰器(decorator)

返璞归真, 看山还是山 刚看到Python装饰器时, 觉得很神奇。简单实验下,发现也就那么回事。但是慢慢的看到越来越多的装饰器。很多时候又不了解到底是怎么回事了。最后还是决定好好研究下。先看看一些实例...
  • TangHuanan
  • TangHuanan
  • 2015-04-17 11:12:38
  • 9584

JavaScript的装饰器:它们是什么及如何使用

装饰器的流行应该感谢在Angular 2+中使用,在Angular中,装饰器因TypeScript能使用。但是在JavaScript中,还处于提议阶段。本文将介绍装饰器是什么,及装饰器如何让代码更加简...
  • owen1190
  • owen1190
  • 2017-06-13 20:37:53
  • 1121

python 缓存装饰器

代码摘自https://github.com/ma6174/pycache 1、使用python内存进行缓存 autocache.py#!/usr/bin/env python #coding=u...
  • liuliuzi_hz
  • liuliuzi_hz
  • 2016-01-12 15:15:50
  • 857

python装饰器(decorator)

什么是装饰器(decorator)   简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象.所以,我们能够在不修改原函数的基础上,在执行原函数前...
  • shuaijiasanshao
  • shuaijiasanshao
  • 2016-05-12 16:05:22
  • 3087
收藏助手
不良信息举报
您举报文章:Python3--装饰器
举报原因:
原因补充:

(最多只允许输入30个字)