什么是装饰器

器即函数

装饰即修饰,意指为其他函数添加新功能

装饰器定义:本质就是函数,功能是为其他函数添加新功能

装饰器需要遵循的原则

1.不修改被装饰函数的源代码(开放封闭原则)

2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

实现装饰器知识储备

装饰器=高阶函数+函数嵌套+闭包

高阶函数

高阶函数定义:
1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

3.满足上述条件任意一个,都可称之为高阶函数

def foo():
print('我的函数名作为参数传给高阶函数')
def gao_jie1(func):
print('我就是高阶函数1,我接收的参数名是%s' %func)
func() def gao_jie2(func):
print('我就是高阶函数2,我的返回值是%s' %func)
return func gao_jie1(foo)
gao_jie2(foo)

高阶函数示范

#高阶函数应用1:把函数当做参数传给高阶函数
import time
def foo():
print('from the foo') def timmer(func):
start_time=time.time()
func()
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式

把函数当做参数传给高阶函数

#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
print('from the foo') def timmer(func):
start_time=time.time()
return func
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能

函数返回值是函数名

高阶函数总结
1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

函数嵌套

def father(name):
print('from father %s' %name)
def son():
print('from son')
def grandson():
print('from grandson')
grandson()
son() father('康明')

闭包

'''
闭包:在一个作用域里放入定义变量,相当于打了一个包
'''
def father(name):
def son():
# name='alex'
print('我爸爸是 [%s]' %name)
def grandson():
# name='wupeiqi'
print('我爷爷是 [%s]' %name)
grandson()
son() father('康明')

无参装饰器

无参装饰器=高级函数+函数嵌套

基本框架

 #这就是一个实现一个装饰器最基本的架子
def timer(func):
def wrapper():
func()
return wrapper

加上参数

 def timer(func):
def wrapper(*args,**kwargs):
func(*args,**kwargs)
return wrapper

加上功能

import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
stop_time=time.time()
print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
return wrapper

加上返回值

import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
return res
return wrapper

使用装饰器

def cal(array):
res=0
for i in array:
res+=i
return res cal=timer(cal)
cal(range(10))

语法糖@

@timer  #@timer就等同于cal=timer(cal)
def cal(array):
res=0
for i in array:
res+=i
return res cal(range(10))

装饰器应用示例

user_list=[
{'name':'alex','passwd':''},
{'name':'linhaifeng','passwd':''},
{'name':'wupeiqi','passwd':''},
{'name':'yuanhao','passwd':''},
] current_user={'username':None,'login':False} def auth_deco(func):
def wrapper(*args,**kwargs):
if current_user['username'] and current_user['login']:
res=func(*args,**kwargs)
return res
username=input('用户名: ').strip()
passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list):
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_user['username']=username current_user['login']=True
res=func(*args,**kwargs)
return res
break
else:
print('用户名或者密码错误,重新登录') return wrapper @auth_deco
def index():
print('欢迎来到主页面') @auth_deco
def home():
print('这里是你家') def shopping_car():
print('查看购物车啊亲') def order():
print('查看订单啊亲') print(user_list)
# index()
print(user_list)
home()

无参装饰器

user_list=[
{'name':'alex','passwd':''},
{'name':'linhaifeng','passwd':''},
{'name':'wupeiqi','passwd':''},
{'name':'yuanhao','passwd':''},
] current_user={'username':None,'login':False}
def auth(auth_type='file'):
def auth_deco(func):
def wrapper(*args,**kwargs):
if auth_type == 'file':
if current_user['username'] and current_user['login']:
res=func(*args,**kwargs)
return res
username=input('用户名: ').strip()
passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list):
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_user['username']=username
current_user['login']=True
res=func(*args,**kwargs)
return res
break
else:
print('用户名或者密码错误,重新登录')
elif auth_type == 'ldap':
print('巴拉巴拉小魔仙')
res=func(*args,**kwargs)
return res
return wrapper
return auth_deco #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
#就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
@auth(auth_type='ldap')
def index():
print('欢迎来到主页面') @auth(auth_type='ldap')
def home():
print('这里是你家') def shopping_car():
print('查看购物车啊亲') def order():
print('查看订单啊亲') # print(user_list)
index()
# print(user_list)
home()

带参装饰器

超时装饰器

import sys,threading,time

class KThread(threading.Thread):

    """A subclass of threading.Thread, with a kill()

    method.

    Come from:

    Kill a thread in Python:

    http://mail.python.org/pipermail/python-list/2004-May/260937.html

    """

    def __init__(self, *args, **kwargs):

        threading.Thread.__init__(self, *args, **kwargs)

        self.killed = False

    def start(self):

        """Start the thread."""

        self.__run_backup = self.run

        self.run = self.__run      # Force the Thread to install our trace.

        threading.Thread.start(self)

    def __run(self):

        """Hacked run function, which installs the

        trace."""

        sys.settrace(self.globaltrace)

        self.__run_backup()

        self.run = self.__run_backup

    def globaltrace(self, frame, why, arg):

        if why == 'call':

          return self.localtrace

        else:

          return None

    def localtrace(self, frame, why, arg):

        if self.killed:

          if why == 'line':

            raise SystemExit()

        return self.localtrace

    def kill(self):

        self.killed = True

class Timeout(Exception):

    """function run timeout"""

def timeout(seconds):

    """超时装饰器,指定超时时间

    若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""

    def timeout_decorator(func):

        """真正的装饰器"""

        def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):

            result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))

        def _(*args, **kwargs):

            result = []

            new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list

                'oldfunc': func,

                'result': result,

                'oldfunc_args': args,

                'oldfunc_kwargs': kwargs

            }

            thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)

            thd.start()

            thd.join(seconds)

            alive = thd.isAlive()

            thd.kill() # kill the child thread

            if alive:

                raise Timeout(u'function run too long, timeout %d seconds.' % seconds)

            else:

                return result[0]

        _.__name__ = func.__name__

        _.__doc__ = func.__doc__

        return _

    return timeout_decorator

@timeout(5)

def method_timeout(seconds, text):

    print('start', seconds, text)

    time.sleep(seconds)

    print('finish', seconds, text)

    return seconds

method_timeout(6,'asdfasdfasdfas')

python学习---装饰器的更多相关文章

  1. Python学习---装饰器/迭代器/生成器的学习【all】

    Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210

  2. Python学习---装饰器的学习1210

    装饰器的基础 学习前提: 作用域 + 函数的理解 + 闭包  [学习,理解] 代码编写原则: 对修改开放对扩展开放 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前 ...

  3. python学习——装饰器函数

    一.装饰器函数的作用是什么 答:装饰器函数是在不修改原函数及其调用方式的情况下对原函数功能进行扩展 对于搞python开发的人来说,函数占据了至关重要的地位.都说学好函数你就可以去找工作了,好了,假如 ...

  4. Python学习——装饰器/decorator/语法糖

    装饰器 定义:本质是函数,为其他函数添加附加的功能. 原则:1.不能修改原函数的源代码 2.不能修改被原函数的调用方式 重点理解: 1.函数即“变量” 2.高阶函数:返回值中包含函数名 3.嵌套函数 ...

  5. day12 python学习 装饰器

    闭包函数: 内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数#函数内部定义的函数称为内部函数 闭包函数获取网络应用 from urllib.request import url ...

  6. python之循序渐进学习装饰器

    python装饰器的定义:在代码运行期间在不改变原函数定义的基础上,动态给该函数增加功能的方式称之为装饰器(Decorator) 装饰器的优点和用途: 1. 抽离出大量函数中与函数功能本身无关的的雷同 ...

  7. python基础 (装饰器,内置函数)

    https://docs.python.org/zh-cn/3.7/library/functions.html 1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使 ...

  8. python初级装饰器编写

    最近项目太忙好久没有学习python了,今天更新一下吧~~ 1.什么是python装饰器: 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返 ...

  9. Python之装饰器、迭代器和生成器

    在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思 ...

随机推荐

  1. varnish 测试

    安装 通过epel 源 yum 安装 [root@localhost varnish]# rpm -ql varnish /etc/logrotate.d/varnish /etc/varnish / ...

  2. Linux 启动时profile、bashrc、~/.bash_profile、~/.bashrc、~/.bash_profile执行顺序以及文件说明

    Linux 启动时profile.bashrc.~/.bash_profile.~/.bashrc.~/.bash_profile执行顺序以及文件说明 一.执行顺序 登录linux时,/etc/pro ...

  3. 详解设计模式在Spring中的应用

    设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆. 今天,在IT学习者网站就设计模式的内在价值做一番探讨,并以spring为例进行讲解,只有领略了其设 ...

  4. es6中promise实现ajax的例子

    function getData(url){ var pro = new Promise(function(resolve,reject){ var xhr = null; try{ xhr = ne ...

  5. Raphael.js--基础1

    Raphael.js 特点: 1.兼容VML和SVG 2.扩展功能——动画 用法: //1.创建画布 let paper=Raphael(x,y,width,height); //2.创建形状 let ...

  6. Bootstrap3基础 栅格系统 col-lg/md/sm/xs-* 简单示例

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  7. The application to execute does not exist: 'C:\Users\Administrator\.dotnet\tools\.store\dotnet-aspnet-codegenerator\2.2.0-rtm-35687\dotnet-aspnet-codegenerator\2.2.0-rtm-35687\tools\netcoreapp2.1\any\

    vs code mvc搭建基架执行命令操作出现的问题解决方式重新复制拷贝一份2.2.0命名为2.2.0-rtm-35687, 修改

  8. export ,export default 和 import 区别 以及用法

    首先要知道export,import ,export default是什么 ES6模块主要有两个功能:export和importexport用于对外输出本模块(一个文件可以理解为一个模块)变量的接口i ...

  9. Visual Studio 禁用诊断工具

    这里以 Visual Studio 2019 为例 调试 - 选项 调试 - 常规 - 禁用调试时启用诊断工具

  10. VWmare设置挂载目录

     [root@localhost ~]# mkdir -p /mnt/cdrom  #首先创建一个挂载目录 [root@localhost ~]# mount -t auto /dev/cdrom / ...