python 装饰器详解

本文深入浅出地介绍了Python装饰器的基础概念与应用实践,包括无参装饰器、带参数装饰器、类装饰器等,并通过具体示例展示了如何使用装饰器来增强函数的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 最简单的装饰器

def decorator(fun):
    print 'decorator befor warpper'
    def wrapper():
        print 'wrapper begin'       
        fun()
        print 'wrapper end'
    return wrapper

@decorator
def decorated_do_something():
    print 'decorated do something'

print decorated_do_something
print '*******************'
print decorated_do_something()

运行结果:

decorator befor warpper
<function wrapper at 0x0000000002BEE828>
*******************
wrapper begin
decorated do something
wrapper end
None

所以:
1. decorated_do_something相当于decorator(decorated_do_something),所以返回是wrapper 方法。
2. decorated_do_something()相当于decorator(decorated_do_something)(), 即wrapper()
测试查看decorated_do_something的函数名:

def decorator(fun):
    print 'decorator befor warpper'
    def wrapper():
        print 'wrapper begin'       
        fun()
        print 'wrapper end'
    return wrapper

@decorator
def decorated_do_something():
    print 'decorated do something'

print decorated_do_something.__name__

运行结果如下:

decorator befor warpper
wrapper

2. 目标函数带固定参数的装饰器


def decorator(fun):
    print 'decorator befor warpper'
    def wrapper(arg):
        print 'wrapper begin'
        print 'arg: '+arg
        fun(arg)
        print 'wrapper end'
    return wrapper

@decorator
def decorated_do_something(arg):
    print 'decorated do something'
    print 'arg: '+arg
def do_something(arg):
    print 'do something'
    print 'arg: '+arg

decorated_do_something('decorated arg')

运行结果如下:

decorator befor warpper
wrapper begin
arg: decorated arg
decorated do something
arg: decorated arg
wrapper end

decorated_do_something(‘decorated arg’)相当于decorator(decorated_do_something)(‘decorated arg’)

3. 目标函数带不固定参数的装饰器

ddef decorator(fun):
    print 'decorator befor warpper'
    def wrapper(*args, **kwargs):
        print 'wrapper begin'
        print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
        fun(*args, **kwargs)
        print 'wrapper end'
    return wrapper

@decorator
def decorated_do_something1(arg):
    print 'decorated do something'
    print 'arg: '+arg
    print 'decorated_do_something1 end' 
@decorator
def decorated_do_something2(*args, **kwargs):
    print 'do something'
    print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
    print 'decorated_do_something2 end' 

decorated_do_something1('only one arg')
print '***************'
decorated_do_something2('arg1','arg2', arg3='arg3',arg4='arg4')

运行结果如下:

decorator befor warpper
decorator befor warpper
wrapper begin
args: ('only one arg',); kwargs: {}
decorated do something
arg: only one arg
decorated_do_something1 end
wrapper end
***************
wrapper begin
args: ('arg1', 'arg2'); kwargs: {'arg3': 'arg3', 'arg4': 'arg4'}
do something
args: ('arg1', 'arg2'); kwargs: {'arg3': 'arg3', 'arg4': 'arg4'}
decorated_do_something2 end
wrapper end

4. 带参数的装饰器

def decorator(arg):
    print 'decorator before _decorator, decorator arg: '+arg
    def _decorator(fun):        
        print 'decorator befor warpper'
        def wrapper(*args, **kwargs):
            print 'wrapper begin'
            print 'args: '+ str(args)+"; kwargs: "+ str(kwargs)
            fun(*args, **kwargs)
            print 'wrapper end'
        return wrapper
    return _decorator

@decorator('2')
def decorated_do_something(arg):
    print 'decorated do something started'
    print 'arg: '+arg
    print 'decorated_do_something end' 


print decorated_do_something.__name__
decorated_do_something("decorated_do_something's arg")

运行结果如下:

decorator before _decorator, decorator arg: 2
decorator befor warpper
wrapper
wrapper begin
args: ("decorated_do_something's arg",); kwargs: {}
decorated do something started
arg: decorated_do_something's arg
decorated_do_something end
wrapper end

5. 被装饰器装饰过的函数的函数名

def decorator(fun):   
    def wrapper(*args, **kwargs):       
        fun(*args, **kwargs)       
    return wrapper
@decorator
def decorated_do_something():
    print 'decorated do something started'

print decorated_do_something.__name__

运行结果:

wrapper

可以看出, decorated_do_something的函数名变成了wrapper,这不是我们想要的。 python的unctools.wraps提供了解决方法

import functools
def decorator(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):       
        fun(*args, **kwargs)       
    return wrapper
@decorator
def decorated_do_something():
    print 'decorated do something started'

print decorated_do_something.__name__

运行结果:

decorated_do_something

6. 装饰器类

需求:让函数只能运行指定次数

class decorator():
    def __init__(self, max):
        self.max=max
        self.count=0
    def __call__(self,fun):
        self.fun=fun
        return self.call_fun
    def call_fun(self, *args, **kw):        
        self.count +=1
        if(self.count>self.max):
            print "%s run more than %d times" %(self.fun.__name__, self.max)
        else:
            self.fun(*args, **kw)


@decorator(2)
def decorated_do_something():
    print 'decorated_do_something running'

@decorator(3)
def decorated_do_something1():
    print 'decorated_do_something1 running'


for i in xrange(4):
    decorated_do_something()
    decorated_do_something1()

运行结果:

decorated_do_something running
decorated_do_something1 running
decorated_do_something running
decorated_do_something1 running
decorated_do_something run more than 2 times
decorated_do_something1 running
decorated_do_something run more than 2 times
decorated_do_something1 run more than 3 times

decorated_do_something相当于 decorator.init(args)(fun)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值