可以这样写吗:
class Test(object):
def _decorator(self, foo):
foo()
@self._decorator
def bar(self):
pass
这个失败了:@self中的self是未知的
我还试过:
@Test._decorator(self)
同样失败:测试未知
我想暂时改变一些实例变量 在装饰器中再运行被装饰的方法 把它们换回来。
可以这样写吗:
class Test(object):
def _decorator(self, foo):
foo()
@self._decorator
def bar(self):
pass
这个失败了:@self中的self是未知的
我还试过:
@Test._decorator(self)
同样失败:测试未知
我想暂时改变一些实例变量 在装饰器中再运行被装饰的方法 把它们换回来。
当前回答
装饰器似乎更适合修改整个对象(包括函数对象)的功能,而不是对象方法的功能,后者通常依赖于实例属性。例如:
def mod_bar(cls):
# returns modified class
def decorate(fcn):
# returns decorated function
def new_fcn(self):
print self.start_str
print fcn(self)
print self.end_str
return new_fcn
cls.bar = decorate(cls.bar)
return cls
@mod_bar
class Test(object):
def __init__(self):
self.start_str = "starting dec"
self.end_str = "ending dec"
def bar(self):
return "bar"
输出结果为:
>>> import Test
>>> a = Test()
>>> a.bar()
starting dec
bar
ending dec
其他回答
我有一个可能有帮助的装饰器的实现
import functools
import datetime
class Decorator(object):
def __init__(self):
pass
def execution_time(func):
@functools.wraps(func)
def wrap(self, *args, **kwargs):
""" Wrapper Function """
start = datetime.datetime.now()
Tem = func(self, *args, **kwargs)
end = datetime.datetime.now()
print("Exection Time:{}".format(end-start))
return Tem
return wrap
class Test(Decorator):
def __init__(self):
self._MethodName = Test.funca.__name__
@Decorator.execution_time
def funca(self):
print("Running Function : {}".format(self._MethodName))
return True
if __name__ == "__main__":
obj = Test()
data = obj.funca()
print(data)
简单的方法。 您所需要做的就是将decorator方法放在类之外。 你仍然可以在室内使用。
def my_decorator(func):
#this is the key line. There's the aditional self parameter
def wrap(self, *args, **kwargs):
# you can use self here as if you were inside the class
return func(self, *args, **kwargs)
return wrap
class Test(object):
@my_decorator
def bar(self):
pass
以下是对迈克尔•施佩尔的回答的进一步扩展:
一个实例方法装饰器,它接受参数并作用于带有参数和返回值的函数。
class Test(object):
"Prints if x == y. Throws an error otherwise."
def __init__(self, x):
self.x = x
def _outer_decorator(y):
def _decorator(foo):
def magic(self, *args, **kwargs) :
print("start magic")
if self.x == y:
return foo(self, *args, **kwargs)
else:
raise ValueError("x ({}) != y ({})".format(self.x, y))
print("end magic")
return magic
return _decorator
@_outer_decorator(y=3)
def bar(self, *args, **kwargs) :
print("normal call")
print("args: {}".format(args))
print("kwargs: {}".format(kwargs))
return 27
然后
In [2]:
test = Test(3)
test.bar(
13,
'Test',
q=9,
lollipop=[1,2,3]
)
start magic
normal call
args: (13, 'Test')
kwargs: {'q': 9, 'lollipop': [1, 2, 3]}
Out[2]:
27
In [3]:
test = Test(4)
test.bar(
13,
'Test',
q=9,
lollipop=[1,2,3]
)
start magic
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-576146b3d37e> in <module>()
4 'Test',
5 q=9,
----> 6 lollipop=[1,2,3]
7 )
<ipython-input-1-428f22ac6c9b> in magic(self, *args, **kwargs)
11 return foo(self, *args, **kwargs)
12 else:
---> 13 raise ValueError("x ({}) != y ({})".format(self.x, y))
14 print("end magic")
15 return magic
ValueError: x (4) != y (3)
装饰器似乎更适合修改整个对象(包括函数对象)的功能,而不是对象方法的功能,后者通常依赖于实例属性。例如:
def mod_bar(cls):
# returns modified class
def decorate(fcn):
# returns decorated function
def new_fcn(self):
print self.start_str
print fcn(self)
print self.end_str
return new_fcn
cls.bar = decorate(cls.bar)
return cls
@mod_bar
class Test(object):
def __init__(self):
self.start_str = "starting dec"
self.end_str = "ending dec"
def bar(self):
return "bar"
输出结果为:
>>> import Test
>>> a = Test()
>>> a.bar()
starting dec
bar
ending dec
你可以装饰装饰器:
import decorator
class Test(object):
@decorator.decorator
def _decorator(foo, self):
foo(self)
@_decorator
def bar(self):
pass