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)

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

  • 相关阅读:
    windwos8.1英文版安装SQL2008 R2中断停止的解决方案
    indwows8.1 英文版64位安装数据库时出现The ENU localization is not supported by this SQL Server media
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
    SQL数据附加问题
    eclipse,myeclipse中集合svn的方法
    JAVA SSH 框架介绍
    SSH框架-相关知识点
    SuperMapRealSpace Heading Tilt Roll的理解
    SuperMap iserver manage不能访问本地目的(IE9)
    Myeclipse中js文件中的乱码处理
  • 原文地址:https://www.cnblogs.com/liuq/p/6093324.html
Copyright © 2011-2022 走看看