装饰器的原理及其用法

什么是装饰器

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理, Web权限校验, Cache等。

装饰器的作用

很有名的例子,就是咖啡,加糖的咖啡,加牛奶的咖啡。 本质上,还是咖啡,只是在原有的东西上,做了“装饰”,使之附加一些功能或特性。例如记录日志,需要对某些函数进行记录,笨的办法,每个函数加入代码,如果代码变了,就悲催了,装饰器的办法,定义一个专门日志记录的装饰器,对需要的函数进行装饰,搞定。装饰器的作用就是为已经存在的对象添加额外的功能。

为什么装饰器要用这样的方式实现?

装饰器的种类根据三个‘对象’的不同搭配一般分为四种:

1.最完整的一种即是带参数的装饰器包装带参数的函数

def decorator_with_params_and_func_args(arg_of_decorator):
    def handle_func(func):
        def handle_args(*args, **kwargs):#如果这样设置参数形式的话,任何形式的func都可以放进来装饰。也就是说第十三行的函数可以是任意函数[搭配任意参数]。
            print "begin" #在此函数内可以对三个‘对象’[arg_of_decorator,func,*args, **kwargs]做任意处理(装饰)。
	    func(*args, **kwargs)
	    print "end"
	    print arg_of_decorator, func, args,kwargs
            return arg_of_decorator #一般有多少个def就有多少个return但是很明显此处不必要,因为在调用的时候[foo4(1, b=3)]一般不必要像返回什么东西,此处有返回所以最后会输出123.
	return handle_args #此处的return的一般是其下一层的函数名
    return handle_func #此处的return的一般是其下一层的函数名

@decorator_with_params_and_func_args("123")
def foo4(a, b=2):
    print "Content" 

print foo4(1, b=3)

输出结果是:

begin

Content

end

123 <function foo4 at 0x204caa0> (1,) {‘b‘: 3}

123

由此我们可以得出一个装饰器的框架来:

def decorator(arg_of_decorator):
    def handle_func(func):
        def handle_args(*args, **kwargs):
            #对三个‘对象’的处理,可以添加一个return。
        return handle_args
    return handle_func

@decorator(arg_of_decorator)
def foo4(*args, **kwargs):
    #任意语句

foo4(*args, **kwargs)#如果上面handle_args函数有返回值的话此处则得到返回的结果。

既然整个框架都得出来了,那么我们可以看一下缺少一种参数的两种情形:不带参数的装饰器包装带参数的函数和带参数的装饰器包装不带参数的函数。

2.不带参数的装饰器包装带参数的函数

def decorator_with_func_args(func):#(arg_of_decorator):这儿可以直接是func做参数,因为少了

装饰器参数所以只有两层两层
    #def handle_func(func):
        def handle_args(*args, **kwargs):
            print "begin"
	    func(*args, **kwargs)
	    print "end"
	    print  func, args,kwargs #arg_of_decorator,
            return 'here have no arg_of_decorator'#arg_of_decorator
	return handle_args #此处返回的仍然是下一层函数的函数名
    #return handle_func

@decorator_with_func_args#("123")这儿不必要有括号和参数了
def foo4(a, b=2):
    print "Content" 

print foo4(1, b=3)

输出结果是:

begin

Content

end

<function foo4 at 0xfeba28> (1,) {‘b‘: 3}

here have no arg_of_decorator

3.带参数的装饰器包装不带参数的函数

def decorator_with_params(arg_of_decorator):
    def handle_func(func):
        #def handle_args(*args, **kwargs):
            print "begin"
	    func()#(*args, **kwargs)
	    print "end"
	    print arg_of_decorator, func#, args,kwargs
            return func#arg_of_decorator 这儿需要返回函数,否则会出现错误:TypeError: 'NoneType' object is not callable
	#return handle_args
    return handle_func 

@decorator_with_params("123")
def foo4():#(a, b=2): 此处不再有参数
    print "Content" 

print foo4()#(1, b=3)

输出的结果为:

begin

Content

end

123 <function foo4 at 0x12a1aa0>

Content

None

这儿为什么需要返回func函数呢?我们看到前面两种情况不需要返回func函数。

4.还有最后一种情况即,不带参数的装饰器包装不带参数的函数

def decorator_with_no_params_and_no_func_args(func):#(arg_of_decorator):
    #def handle_func(func):
        #def handle_args(*args, **kwargs):
            print "begin"
	    func()#(*args, **kwargs)
	    print "end"
	    print func#arg_of_decorator, func, args,kwargs
            return func#arg_of_decorator
	#return handle_args
    #return handle_func 

@decorator_with_no_params_and_no_func_args#("123")
def foo4():#(a, b=2):
    print "Content" 

print foo4()#(1, b=3)<strong>
</strong>

输出结果为:

begin

Content

end

<function foo4 at 0xb2ba28>

Content

None

装饰器的原理及其用法

时间: 2024-10-08 23:06:10

装饰器的原理及其用法的相关文章

【Python基础】装饰器的解释和用法

装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩进 def sample(): return 1 print(sample()) 作用域 函数内部的变量和函数外的变量是不同的 我们看一下下面的例子,locals()和globals()方法会得到局部变量和全局变量 我们可以在函数中调用全局变量,但是无法在函数中改变全局变量的值 global_str

【转】【python】装饰器的原理

写在前面: 在开发OpenStack过程中,经常可以看到代码中的各种注解,自己也去查阅了资料,了解了这是python中的装饰器,因为弱类型的语言可以将函数当成返回值返回,这就是装饰器的原理. 虽然说知道装饰器的使用方法以及原理,但是一直不明白为什么要通过在内部函数返回一个函数名这样的写法,在微信上看到下面这篇文章,豁然开朗.因为觉得写的非常好,所以我也没必要再来写一遍了,直接转载,供以后的开发中参考. -----------------------------------------------

Python 装饰器工作原理解析

#!/usr/bin/env python #coding:utf-8 """ 装饰器实例拆解 """ def login00(func):     print('00请通过验证用户!')     return func def tv00(name):     print('00你的用户是:%s' %name) # 装饰器的精简工作原理解释: tv = login00(tv00) # 返回tv函数的对象,赋值给tv tv('yh00') # 调用

python中装饰器的原理

装饰器这玩意挺有用,当时感觉各种绕,现在终于绕明白了,俺滴个大爷,还是要慢慢思考才能买明白各种的真谛,没事就来绕一绕 def outer(func): def inner(): print("认证成功") result=func() print("登录成功") return result return inner@outerdef OA(): print("OA接口") 这里面需要注意的是: @outer和@outer()有区别,没有括号时,ou

一篇文章搞懂装饰器所有用法

如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起.在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,这顶帽子我们称之为装饰函数 或 装饰器. 你要问我装饰器可以实现什么功能?我只能说你的脑洞有多大,装饰器就有多强大. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以用类.偏函数实现) 再

装饰器的完整实现及原理

1.简单装饰器 说明:代码在下边.装饰前后,我们都打印一遍如下内容,做一下对比. print(foo)           # 打印当前函数对象 print(foo.__name__)  # 打印foo函数的函数名 print(foo.__doc__)   # 打印foo函数的文档字符串(docString) 装饰之前: <function foo at 0x000002569AAB5620> foo this is foo 装饰之后: <function check_result.&l

Python装饰器的另类用法

之前有比较系统介绍过Python的装饰器,本文算是一个补充.今天我们一起探讨一下装饰器的另类用法. 语法回顾 开始之前我们再将Python装饰器的语法回顾一下. @decorate def f(...): pass 等同于: def f(...): pass f = decorate(f) @语法的好处在于: 相同的函数名只出现一次,避免了f = decorate(f)这样的语句. 可读性更高,让读代码的人一眼就明白函数被装饰了哪些功能. @call()装饰器 假设你要创建一个整数平方的列表,你

Python装饰器由浅入深

装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

python 3.x 的装饰器笔记

今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python 2.7在用法上差不多. 现在某个视频公司有一段代码,,代码的主要功能就是看电影. 1 def watchfilm(): 2 print('You are watching film now....') 3 4 watchfil() 运行之后输出: You are watching film now