[英]How to replace decorator with method in python class
So let's say i have the following code where I am using the get_duration decorator to print out how long a method lasted. 所以,假设我有以下代码,我使用get_duration装饰器打印方法持续多长时间。
import datetime
import time
def get_duration(function):
def wrapper(*args, **kwargs):
start = datetime.datetime.now()
print "starting process %s()" %function.__name__
function(*args, **kwargs)
end = datetime.datetime.now()
print "Process lasted: ", end - start
return wrapper
class Operations(object):
def __init__(self, a, b):
self.a = a
self.b = b
@get_duration
def add(self):
time.sleep(1)
print self.a + self.b
@get_duration
def sub(self):
time.sleep(1)
print self.a - self.b
my_class = Operations(2, 98)
my_class.add()
my_class.sub()
Output 产量
>> starting process add()
>> 100
>> Process lasted: 0:00:01.000260
>> starting process sub()
>> -96
>> Process lasted: 0:00:01.001161
Can i replace this with a class method or something like (pseudo code following): 我可以用类方法或类似的方法替换它(伪代码跟随):
my_class = Operations(2, 98)
my_class.add.get_duration #runs add(), prints duration
my_class.add #runs add() does not print duration
To do exactly that you want, you can decorate this method by the callable class. 要完全按照您的意愿执行,您可以通过可调用类来装饰此方法。
class TimeElapser :
def __init__(self, function_to_wrap) :
self.__call__ = function_to_wrap
self.get_duration = get_duration(function_to_wrap)
Examples : 例子 :
class Foo :
@TimeElapser
def do_something(self, ....) :
...
foo = Foo()
foo.do_something() #Does something
foo.do_something.get_duration() # Does something and print duration
Something like this? 像这样的东西?
def map_func(function):
def wrapper(*args, **kwargs):
start = datetime.datetime.now()
print "starting process %s()" %function.__name__
function(*args, **kwargs)
end = datetime.datetime.now()
print "Process lasted: ", end - start
function.get_duration = wrapper
return function
Demo: 演示:
>>> c = Operations(100, 200)
>>> c.add()
c.300
>>> c.sub()
-100
>>> c.add.get_duration(c)
starting process add()
300
Process lasted: 0:00:01.001584
>>> c.sub.get_duration(c)
starting process sub()
-100
Process lasted: 0:00:01.003768
You can do this: 你可以这样做:
def get_duration(function):
def wrapper(*args, **kwargs):
kwargs['self'].elapsed_time = timeit.timeit('function(*args, **kwargs)',
"from __main__ import function, args, kwargs",
number=1)
return wrapper
Then you can read elapsed_time
var to get the time. 然后你可以读取elapsed_time
var来获取时间。
I think this is a good use case for metaprogramming like so: 我认为这是元编程的一个很好的用例,如下所示:
import types
def my_dec(f):
print "decorated"
return f
class MyMetaprogrammingDecoratorClass(object):
def __getattr__(self, attribute):
try:
## we should honor inherited classes that may have defined __getattr__
return super(MyMetaprogrammingDecoratorClass, self).__getattr__(attribute)
except AttributeError:
if attribute.endswith("_decorated"):
output = object.__getattribute__(self, attribute.replace("_decorated",""))
if isinstance(output, types.MethodType):
return my_dec(output)
else:
raise AttributeError
else:
raise AttributeError
class MyCustomClass(MyMetaprogrammingDecoratorClass):
def f(self):
return 1
g = MyCustomClass()
print g.f()
>> 1
print g.f_decorated()
>> decorated
>> 1
So you can just postfix any method with _decorated
and it the class will know to decorate that method with my_dec
, if it exists. 所以你可以使用_decorated
后缀任何方法,如果它存在,类将知道用my_dec
装饰该方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.