最基本的修饰器包括了无参数的修饰器和带参数的修饰器,这两种修饰器都是针对函数的,讲解的博客已经很多了,就不再赘述了,这里重点讲下修饰器的几种特殊用法。
因为类也是可以callable的,只要实现__call__
魔法函数即可,所以类也可以实现修饰器效果。
import functools
class Debug(object):
def __init__(self, function):
self.function = function
functools.update_wrapper(self, function)
def __call__(self, *args, **kwargs):
output = self.function(*args, **kwargs)
print('%s(%r, %r): %r' % (self.function.__name__, args, kwargs, output))
return output
@Debug
def spam(eggs):
return "spam" * (eggs%5)
spam(3)
结果如下所示:
spam((3,), {}): 'spamspamspam'
使用类创建修饰器和使用函数创建修饰器的区别是,后者使用 functools.wraps
,前者使用
functools.update_wrapper
。
修饰类的方法与修饰函数形式差不多,唯一需要注意的是类方法中必须提供第一个变量self
。
import functools
def plus_one(function):
@functools.wraps(function)
def _plus_one(self, n):
return function(self, n+1)
return _plus_one
class Spam(object):
@plus_one
def get_eggs(self, n):
return n*"eggs"
spam = Spam()
print(spam.get_eggs(2))
结果如下所示:
eggseggseggs
classmethod
、staticmethod
和property
描述器本质上都是类方法修饰器。classmethod
和staticmethod
的区别是classmethod
只需要传递类对象,staticmethod
既不用传递类对象也不用传递类的实例。
首先看下classmethod
和staticmethod
的用法
import pprint
class Spam(object):
def some_instancemethod(self, *args, **kwargs):
print("self: %r" % self)
print("args: %s" % pprint.pformat(args))
print("kwargs: %s" % pprint.pformat(kwargs))
@classmethod
def some_classmethod(cls, *args, **kwargs):
print("cls: %r" % cls)
print("args: %s" % pprint.pformat(args))
print("kwargs: %s" % pprint.pformat(kwargs))
@staticmethod
def some_staticmethod(*args, **kwargs):
print("args: %s" % pprint.pformat(args))
print("kwargs: %s" % pprint.pformat(kwargs))
spam = Spam()
spam.some_instancemethod(1,2, a=3, b=4)
Spam.some_classmethod()
spam.some_classmethod()
Spam.some_classmethod(1,2, a=3,b=4)
Spam.some_staticmethod()
Spam.some_staticmethod(1,2,a=3,b=4)
结果如下所示:
self: <__main__.Spam object at 0x000001AF5FF335F8>
args: (1, 2)
kwargs: {'a': 3, 'b': 4}
cls: <class '__main__.Spam'>
args: ()
kwargs: {}
cls: <class '__main__.Spam'>
args: ()
kwargs: {}
cls: <class '__main__.Spam'>
args: (1, 2)
kwargs: {'a': 3, 'b': 4}
args: ()
kwargs: {}
args: (1, 2)
kwargs: {'a': 3, 'b': 4}