zoukankan      html  css  js  c++  java
  • Python 之 装饰器的写法

    普通装饰器

    1. 不带参数的普通装饰器

     1 from functools import wraps
     2 
     3 def use_logging(func):
     4     @wraps(func)    # 使得装饰器函数和原函数有一样的原信息(docstring、__name__等),但为方便,下面的例子没有使用。
     5     def wrapper(*args, **kw):
     6         print args
     7         print kw
     8         return func(*args, **kw)
     9     return wrapper
    10  
    11 @use_logging
    12 def foo(x, n=1):
    13     print x, n
    14     print 'I am foo'
    15      
    16 foo(3)
    17 foo(1, n=2)

    输出如下:

    # foo(3)
    (3,)
    {}    # 因为foo(x, n=1)是在user_logging之后调用的,foo(3)时并未传其他参数,所以这里输出为空。
    3 1
    I am foo
    
    # foo(1, n=2)
    (1,)
    {'n': 2}
    1 2
    I am foo

    2. 带参数的普通装饰器

     1 def use_logging(level):
     2     def decorator(func):
     3         def wrapper(*args, **kw):
     4             if level == 'warning':
     5                 print '%s is running' % func.__name__
     6             return func(*args, **kw)
     7         return wrapper
     8     return decorator
     9 
    10 @use_logging(level='warning')
    11 def foo(name='FOO'):
    12     print 'I am %s' % name
    13     
    14 @use_logging(level='info')
    15 def bar(name='BAR'):
    16     print 'I am %s' % name
    17 
    18 foo()
    19 bar()

    输出:

    # foo()
    foo is running
    I am FOO
    
    # bar()
    I am BAR

    装饰器类

    类装饰器具有灵活度大、高内聚、封装性等优点。当使用 @ 形式将装饰器附加到函数上时,就会调用 __call__() 方法。

    1. 不带参数的装饰器类

     1 class FOO(object):
     2     def __init__(self, func):
     3         self._func = func
     4         
     5     def __call__(self, *args, **kw):
     6         print args, kw
     7         kw['x'] = 34
     8         return self._func(*args, **kw)
     9         
    10 @FOO
    11 def bar(a, x=1):
    12     print a, x
    13     print 'I am bar'
    14     
    15 bar(3,x=7)

    输出:

    (3,) {'x': 7}
    3 34
    I am bar

    2. 带参数的装饰器类

     1 class FOO(object):
     2     def __init__(self, level='debug'):
     3         self._level = level
     4         
     5     def __call__(self, func):
     6         def _call(*args, **kw):
     7             print args, kw
     8             if self._level == 'error':
     9                 kw['x'] = 34
    10             return func(*args, **kw)
    11         return _call
    12         
    13 @FOO('error')   # FOO()
    14 def foo(a, x=1):
    15     print a, x
    16     print 'I am foo'
    17     
    18 @FOO('info')
    19 def bar(a, x=1):
    20     print a, x
    21     print 'I am bar'
    22 
    23 foo(2)
    24 bar(3,x=7)

    输出:

    # foo(2)
    (2,) {}
    2 34
    I am foo
    
    # bar(d, x=7)
    (3,) {'x': 7}
    3 7
    I am bar

    另外一种带参数的装饰器类的写法如下:

     1 class FOO(object):
     2     def __init__(self, level):
     3         self._level = level
     4         
     5     def __call__(self, func):
     6         self._func = func
     7         return self._call
     8     
     9     def _call(self, *args, **kw):
    10         print args, kw
    11         if self._level == 'error':
    12             kw['x'] = 34
    13         return self._func(*args, **kw)
    14 
    15 @FOO('error')
    16 def foo(a, x=1):
    17     print a, x
    18     print 'I am foo'
    19     
    20 @FOO(level='info')
    21 def bar(a, x=1):
    22     print a, x
    23     print 'I am bar'
    24 
    25 foo(2)
    26 bar(3,x=7)

    输出的结果如上面的一致,注意加粗的地方。

  • 相关阅读:
    Splay 详解
    莫队套值域分块
    浅谈区间众数
    回滚莫队分块
    带修莫队分块
    微服务规划准则
    mysql查询包含逗号的数据,并逗号拆分为多行展现
    python mysql 单连接和连接池简单示例
    代理模式八:装饰者模式
    代理模式七:迭代器模式
  • 原文地址:https://www.cnblogs.com/liuq/p/6093324.html
Copyright © 2011-2022 走看看