关注earlier thread我的问题是如何使用此表达式:fn(self,*args, **kwargs
并以此方式调用它self.fn(...)
这是我的整个程序,其中包含失败的行评论出:
def formatHeader(fn):
def wrapped(*args, **kwargs):
print "here is args prior to extraction - {0}".format(args)
if len(args) > 1:
self,args = args # remove self from args
else:
self, args= args[0], ()
print("Here are the arguments after extraction: {0} {1}".format(self, args))
#return '<div class="page_header">' + self.fn(*args, **kwargs)+'</div>'
return '<div class="page_header">' + fn(self,*args, **kwargs)+'</div>'
return wrapped
class MyPage(object):
def __init__(self):
self.PageName = ''
def createPage(self):
pageHeader = self.createHeader()
return pageHeader
def addem(self, a, b):
return a + b
@formatHeader #<----- decorator
def createHeader(self):
return "Page Header " + self.PageName
obj = MyPage()
print obj.createHeader()
答案 0 :(得分:3)
首先,该范围内不存在self
。 self
是一个标签,按惯例引用类的实例方法中的当前实例。其次,装饰器并不意味着要知道它们正在包装的函数的实例(至少在默认情况下)。该方法绑定到实例,并且装饰器对绑定方法进行操作,该方法作为可调用的黑盒子传递。如果你想从装饰器中访问实例成员(你不应该这样做,因为它实际上会破坏oo),你必须将实例传递给装饰器,这意味着将装饰器封闭在另一个封闭器中,或者使用内省从装饰器代码中动态发现拥有的实例。
答案 1 :(得分:1)
问题是你的包装器想要访问它所应用的实例的另一个方法,但它直到运行时才传递 - 而不是类定义时间,即装饰器运行时)。基本上你需要一个特定于实例的方法装饰器。您可以通过使装饰器成为class method decorator using instance中PythonDecoratorLibrary配方中描述的描述符来实现此目的。
这是应用于您的示例代码(有一些外观变化):
from functools import wraps
def formatHeader(fn):
class Descriptor(object):
def __init__(self, fn):
self.fn = fn
def __get__(self, instance, klass):
if instance is None: # Class method was requested
return self.make_unbound(klass) # will raise TypeError
return self.make_bound(instance)
def make_unbound(self, klass):
@wraps(self.fn)
def wrapped(*args, **kwargs):
'''This documentation will vanish :)'''
raise TypeError(
'unbound method {}() must be called with {} instance '
'as first argument (got nothing instead)'.format(
self.fn.__name__, klass.__name__)
)
return wrapped
def make_bound(self, instance):
@wraps(self.fn)
def wrapped(*args, **kwargs):
'''This documentation will disapear :)'''
return ('<div class="page_header">' +
self.fn(instance, *args, **kwargs) + '</div>')
# This instance does not need the descriptor anymore,
# let it find the wrapped method directly next time:
setattr(instance, self.fn.__name__, wrapped)
return wrapped
return Descriptor(fn)
class MyPage(object):
def __init__(self):
self.PageName = ''
def createPage(self):
pageHeader = self.createHeader()
return pageHeader
def addem(self, a, b):
return a + b
@formatHeader #<----- decorator
def createHeader(self):
return "Page Header " + self.PageName
obj = MyPage()
print obj.createHeader()
请注意,嵌套Descriptor类方法中的self
参数引用Descriptor类的实例,而不是其方法被包装的类(代码中为instance
)。