栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

我对python装饰器的理解-秒懂

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

我对python装饰器的理解-秒懂

因为高阶函数的存在,可以接受函数传参,这就让不改变原有函数的前提下,“装饰”原有函数成为可能。也就是增强其功能。

不带参数的装饰器

实现不带参数的装饰器至少需要这样两步操作:

可以看出,不带参数的装饰器实现有两个步骤:

  1. 传入原函数名
  2. 传入原函数参数列表,增加功能代码,调用原函数
    两个步骤之间的链接,是用return返回函数名进行指向(闭包)。
带参数的装饰器

类比不带参数的装饰器实现步骤,每一次传参,就需要定义一次函数,并完成内外层函数的指向调用,类似与递归。
因此不难想象,当我们本身的装饰器也需要参入特定参数时,我们就需要把不带参数的装饰器再进行一次封装,在传入原函数前,增加一个传参和指向的过程。
如下:

可以看出,带参数的装饰器实现就多了一个传送装饰参数的过程,就多了一层。

实例对比

不带参数的装饰器

 def log_decorator(f):
     def wrapper(*args,**kw):
  print '%s()...'%f.__name__
  return f(*args,**kw)
     return wrapper

带参数的装饰器

 def log(prefix):
 def log_decorator(f):
     def wrapper(*args,**kw):
  print '[%s]%s()...'%(prefix,f.__name__)
  return f(*args,**kw)
     return wrapper
 return log_decorator

从上面两个实例对比可以看出,带参数与不带参数,就是多了一层封装,多的这一层,提供了传参的入口。

类装饰器

类装饰器,相比函数装饰器,具有灵活度大、高内聚、封装性等优点。

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

    def __call__(self):
 print 'class decorator runing'
 self._func()
 print 'class decorator ending'

@Foo
def bar():
    print 'bar'

bar()

使用装饰器极大复用了代码,但是也有缺点就是原函数元信息不见了,比如函数的docstring、name、参数列表

装饰器

def logged(func):
    def with_logging(*args, **kwargs):
 print func.__name__ + 'was called'
 return func(*args, **kwargs)
    return with_logging

函数

@logged
def f(x):
    """does some math"""
    return x + x*x

# 等价于f = logged(f)

不难发现,函数f被with_logging取代了,当然它的docstring,name就是变成了with_logging函数的信息了。

print f.__name__    # 'with_logging'
print f.__doc__# 'None'

怎么解决,这里有个functools.wraps,wraps本身也是一个装饰器,它能把元函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了。

from functools import wraps
def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
 print func.__name__ + 'was called'
 return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
    """does some math"""
    return x + x*x

print f.__name__# 'f'
print f.__doc__   # 'does some math'
内置装饰器

@staticmethod

@classmethod

@property

装饰器的顺序
@a
@b
@c
def f():
    pass

# 等效于 
f = a(b(c(f)))
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号