在Python中,是否可以用同一个decorator来修饰类和非类方法?

2024-10-01 11:22:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的异常日志装饰器,当脚本抛出异常时,它可以方便地向自己发送电子邮件。在

def logExceptions(func):
   def wrapper():
      try:
         func()
      except Exception, e:
         logger.exception(e)

   return wrapper

但是,如果我想修饰一个类方法,我必须修改wrapper()以获取“self”,否则会出现以下错误:

^{pr2}$

当然,在这一点上,我不能用它来修饰任何非类方法,因为这样就会出现以下错误:

TypeError: wrapper() takes exactly 1 argument (0 given)

有没有一个干净的方法来解决这个问题?谢谢您=)


Tags: 方法脚本电子邮件def错误exception装饰logger
3条回答

装饰的另一种选择是使用^{},这是一个回调函数,它对所有未捕获的异常进行操作,您可以将自定义日志记录函数分配给这些异常。这样做的好处是,您不需要mutilate(更重要的是,跟踪)您对记录异常感兴趣的每个函数。在

实例方法classmethodstaticmethod之间的区别

首先要说明的是:静态方法和类方法都是函数,所以标准函数规则大多适用于它们。我知道你的问题是关于静态方法类方法之间的区别(后者在第一个参数中接收类):

class Test(object):
    def standard_method(*args, **kwargs):
        # it is instance method (first argument will be instance)
        return args, kwargs

    @classmethod
    def class_method(*args, **kwargs):
        # it is class method (first argument will be class)
        return args, kwargs

    @staticmethod
    def static_method(*args, **kwargs):
        # it is static method (receives only arguments passed explicitly)
        return args, kwargs

证据(或者更确切地说是不言而喻的例子)如下:

^{pr2}$

如您所见,传递的参数列表因选择的方法类型而异。您面临的问题是可变参数数。在

解决方案

有一种解决方法可以用于-use参数解包:

def some_decorator(func):
    def wrapper(*args, **kwargs):
        # do something here
        # args is a tuple with positional args, kwargs is dict with keyword args
        return func(*args, **kwargs)
    return wrapper

之后,some_decorator返回的函数将接受与修饰函数相同数量的参数。在

因此,这两个例子都会起作用:

@some_decorator
def say_hello():
    print 'hello'

@some_decorator
def say_something(something):
    print something

附录

为了给您一个完整的例子,最好使用这样的结构(注意functools.wraps的用法):

from functools import wraps
def some_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # do something here
        # args is a tuple with positional args, kwargs is dict with keyword args
        return func(*args, **kwargs)
    return wrapper

其原因在documentation for ^{}中列出:它保留了函数名和docstring,有效地使包装看起来像一个包装好的函数(这有时很有用)。在

通常的做法是定义包装器,以便它接受*args和{},并将它们传递给它包装的函数。这样它就可以包装任何函数。在

另外,我得到的印象是,您所称的“类方法”是Python所称的“实例方法”,而您所称的“非类方法”是Python所称的“函数”。Python中的“非类方法”(例如,实例方法)接受一个self参数。在

相关问题 更多 >