python-如何在类内部装饰方法?

我正在尝试装饰类中的方法,但python抛出错误。 我的课看起来像这样:

from pageutils import formatHeader

class myPage(object):
   def __init__(self):
      self.PageName = ''

   def createPage(self):
      pageHeader = self.createHeader()

   @formatHeader   #<----- decorator
   def createHeader(self):
       return "Page Header ",self.PageName

if __name__=="__main__":
   page = myPage()
   page.PageName = 'My Page'
   page.createPage()

pageutils.py

def formatHeader(fn):
   def wrapped():
       return '<div class="page_header">'+fn()+'</div>'
   return wrapped

Python抛出以下错误

self.createHeader()
TypeError: wrapped() takes no arguments (1 given)

我要去哪里玩?

gath asked 2020-01-14T11:33:19Z
3个解决方案
60 votes

您将忽略未修饰函数(在您的情况下为createHeader)中存在的self参数。

def formatHeader(fn):
    from functools import wraps
    @wraps(fn)
    def wrapper(self):
        return '<div class="page_header">'+fn(self)+'</div>'
    return wrapper

如果不确定要装饰的函数的签名,可以按如下所示使其更通用:

def formatHeader(fn):
    from functools import wraps
    @wraps(fn)
    def wrapper(*args, **kw):
        return '<div class="page_header">'+fn(*args, **kw)+'</div>'
    return wrapper
krawyoti answered 2020-01-14T11:34:07Z
34 votes

Python自动将类实例作为参考传递。 (2702204064565565298176参数在所有类方法中均可见)。

您可以这样做:

def formatHeader(fn):
    def wrapped(self=None):
        return '<div class="page_header">'+fn(self)+'</div>'
    return wrapped
exhuma answered 2020-01-14T11:33:42Z
1 votes

您也可以在运行时(而不是在定义时)修饰该方法。 例如,在您无权访问或不想编辑源代码的情况下,这可能很有用。


In [1]: class Toy():
   ...:     def __init__(self):
   ...:         return
   ...:     def shout(self, s):
   ...:         print(s)
   ...:

In [2]: def decor(fn):
   ...:     def wrapper(*args):
   ...:         print("I'm decorated")
   ...:         return fn(*args)
   ...:     return wrapper
   ...:


In [4]:

In [4]: a=Toy()

In [5]: a.shout('sa')
sa

In [6]: a.shout=decor(a.shout)

In [7]: a.shout('sa')
I'm decorated
sa

Sibbs Gambling answered 2020-01-14T11:34:27Z
translate from https://stackoverflow.com:/questions/1367514/how-to-decorate-a-method-inside-a-class