如何在类内装饰方法?
我正在尝试给一个类里的方法加装饰器,但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)
我哪里搞错了呢?
3 个回答
2
你也可以在程序运行的时候给方法加装饰,但不能在定义的时候加。这在你无法访问或者不想修改源代码的情况下会很有用,比如说。
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
68
你漏掉了一个叫做self的参数,这个参数在你没有装饰器的函数里是有的(在你的例子中是createHeader)。
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
47
在Python中,当你使用一个类的实例时,它会自动把这个实例作为引用传递给方法。这就是我们在所有实例方法中看到的那个self
参数。
你可以这样做:
def formatHeader(fn):
def wrapped(self=None):
return '<div class="page_header">'+fn(self)+'</div>'
return wrapped