您的位置:首页 > 编程语言 > Python开发

Python中装饰器的理解

2016-09-18 00:00 435 查看

1. 什么是装饰器?

函数装饰器是一种函数运行时的声明。使用方法是在定义一个函数(比如def func)前一行添加"@someDecorator"。如:

def someDecorator(func):
return func

@someDecorator
def func1():
...


2. 装饰器的本质

在上述例子中,someDecorator是一个单参数的可调用对象,他返回一个与func1具有相同数目的参数的可调用对象(func)。解释器在碰到装饰器的时候,会将上述代码解释成func1 = someDecorator(func1),所以在调用func1的时候,实际上调用的是someDecorator(func1)()。

在声明装饰器的时候,会解释成func1 = someDecorator(func1)这么一个赋值语句,所以调用过程是:先调用someDecorator,然后返回func, 再把func赋值给func1。因此装饰器会在装饰的时候被执行一次。

3.class和decorator

用类作装饰器时,被装饰函数通过构造函数传入。

class MyDecorator:
def __init__(self, fn):
print "decorator function: __init__"
self.fn = fn

def __call__(self):
print "decorator function: __call__"
self.fn()

"""
装饰器被解释时,会调用一次且只调用一次构造函数,所以会调用__init__
"""
@MyDecorator
def hello():
print "hello"

print "End decoration"

hello()
hello()

"""
输出:
decorator function: __init__
End decoration
decorator function: __call__
hello
decorator function: __call__
hello
"""


4.带参数的decorator

def login(*args, **kwargs):
def realDecorator(fn):
print "welcome {0}".format(kwargs.get("userName", "guest"))
def wrapper(*args, **kwargs):
fn()
return wrapper
return realDecorator

"""
该段代码解释成hello = login(userName="holton")(hello)
(1)先由login(userName="holton")返回装饰器realDecorator
(2)然后hello = realDecorator(hello), 即hello = wrapper

装饰器是login(userName="holton"),不是login
因此真正的装饰器是login(userName="holton")返回的函数,即realDecorator
"""
@login(userName="holton")
def hello():
print "hello"

hello()

对于类形式的装饰器,如果装饰器带参数,则fn不能通过init函数传入,则通过call传入。

# -*- coding:utf-8 -*-

class MyDecorator:
def __init__(self, userName):
print "decorator function: __init__"
self.userName = userName

def __call__(self, fn):
print "decorator function: __call__"
def wrapper():
print "welcome {0}".format(self.userName)
fn()
return wrapper

"""
装饰器带参数,fn不能通过init传入,只能通过call传入
在call中返回一个真正的装饰器
"""
@MyDecorator(userName="holton")
def hello():
print "hello"

print "End decoration"

hello()

"""
输出:
decorator function: __init__
decorator function: __call__
End decoration
welcome holton
hello
"""

通过上面的输出可以看出,装饰完成的时候,__call__函数已经被调用了。

5.被装饰的函数带参数

6. 函数装饰器示例

"""
装饰器是一个单参数的可调用对象,他返回一个与func具有相同数目的参数的可调用对象。
"""
def decorator(f
7fe8
unc):
print "Begin of decorator"
def wrapper(a, b):
print "In wrapper"
func(a, b)
return wrapper

"""
装饰器实际上是在调用add的使用,把add(a, b)映射成decorator(add)(a, b)
即先调用decorator(add),返回wrapper,然后进而调用wrapper(a, b)
"""
@decorator
def add(a, b):
print "In add: %s" % (a+b)

"""
在调用add函数的时候,他会自动调用装饰器所返回的对象(即wrapper)
注意装饰器返回的对象可以是最初的函数本身(add)或其他对象(wrapper)
"""
add(1, 2)
add(3, 4)

"""
上述代码的输出:
Begin of decorator
In wrapper
In add: 3
In wrapper
In add: 7

注意"Begin of decorator"只打印了一次,因为装饰器实际上只运行一次(在装饰的时候)
"""


7.参考文档

本文主要参考陈皓前辈的装饰器文章,基本是这篇文章的个人理解,链接:
http://coolshell.cn/articles/11265.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息