Форум сайта python.su
0
Всем день добрый, захотелось не много странного. Можно ли сделать декоратор который бы возвращал, помимо декорируемой функции, дополнительный объект, при этом для кода, который бы вызывал функцию, продолжал думать что это функция.
Хотел возвращать объект который может вести себя как функция, но что - то не срослось. Задача стоит в профилировании тире логировании методов вот пример кода того что хотел сделать но не вышло.
class StatData(): def __init__(self): self.start_time = None self.delta_time = None self.return_obj = None self.function_name = None self.position_args = None self.named_args = None class StatResult(): def __init__(self,f,data): self.func = f self.data = data def __call__(self): return self.func def timing_decorator(callback): item = StatData() def func(f): def decor(*args,**kwargs): start = time.time() item.start_time = datetime.now() item.position_args = list(args) item.named_args = [e for e in kwargs.iteritems()] ret = f(*args,**kwargs) end = time.time() item.delta_time = end - start item.return_obj = ret item.function_name = f.__name__ callback(item) return ret return decor return (func,item)
Офлайн
88
То есть там где ожидается функция будет список, со всеми проистекающими.
Отредактировано Shaman (Май 22, 2014 12:11:53)
Офлайн
568
Я не очень понял, что нужно, но возможно Вам поможет такой хак: функция, это собственно тоже объект, можете назначать ей любые атрибуты
def decorator(**kwargs): def wrapper(func): def function(*args, **kw): return func(*args, **kw) for k, v in kwargs.iteritems(): setattr(function, k, v) return function return wrapper @decorator(a=1) def foo(x): print foo.a print x ** 2 foo(2) print foo.a
Офлайн
0
ShamanВыше в примере я там как раз создал класс который callable, но что - то не взлетело я его сначала пытался возвращать. Вот переделанный вариант с callable классом
То есть там где ожидается функция будет список, со всеми проистекающими.
class StatData(): def __init__(self): self.start_time = None self.delta_time = None self.return_obj = None self.function_name = None self.position_args = None self.named_args = None class StatResult(): def __init__(self,f,data): self.func = f self.data = data def __call__(self): return self.func def timing_decorator(callback): item = StatData() def func(f): def decor(*args,**kwargs): start = time.time() item.start_time = datetime.now() item.position_args = list(args) item.named_args = [e for e in kwargs.iteritems()] ret = f(*args,**kwargs) end = time.time() item.delta_time = end - start item.return_obj = ret item.function_name = f.__name__ callback(item) return ret return decor return StatResult(func,item)
result = some_function_with_magic_deocrator(some_arg)
result, metadata = some_function_with_magic_deocrator(some_arg)
Отредактировано gingray (Май 22, 2014 12:42:47)
Офлайн
88
gingrayЯ не предложил ничего из неиспробованного на практике.
Выше в примере я там как раз создал класс который callable, но что - то не взлетело я его сначала пытался возвращать.
import time from datetime import datetime class StatData(object): def __init__(self): self.start_time = None self.delta_time = None self.return_obj = None self.function_name = None self.position_args = None self.named_args = None class StatResult(object): def __init__(self,f,data): self.func = f self.data = data def __call__(self): return self.func() def timing_decorator(callback): item = StatData() def func(f): def decor(*args,**kwargs): start = time.time() item.start_time = datetime.now() item.position_args = list(args) item.named_args = [e for e in kwargs.iteritems()] ret = f(*args,**kwargs) end = time.time() item.delta_time = end - start item.return_obj = ret item.function_name = f.__name__ callback(item) return ret return StatResult(decor,item) return func def cb(arg): print "don't call my back!" @timing_decorator(cb) def foo(): print 'it here' foo() print foo.data.delta_time
>>> it here don't call my back! 0.00723195075989 >>>
Офлайн
0
Спасибо думаю то что нужно, еще осваиваюсь с Python'ом! Зачет.
Офлайн