Уведомления

Группа в Telegram: @pythonsu

#1 Май 22, 2014 12:00:23

gingray
Зарегистрирован: 2014-05-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

Всем день добрый, захотелось не много странного. Можно ли сделать декоратор который бы возвращал, помимо декорируемой функции, дополнительный объект, при этом для кода, который бы вызывал функцию, продолжал думать что это функция.
Хотел возвращать объект который может вести себя как функция, но что - то не срослось. Задача стоит в профилировании тире логировании методов вот пример кода того что хотел сделать но не вышло.

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)

Офлайн

#2 Май 22, 2014 12:10:49

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

То есть там где ожидается функция будет список, со всеми проистекающими.

  • можно вернуть callable object
  • можно заполнять внешнюю по отношению к функции и декоратору структуру доп. атрибутов
  • можно назначать доп. атрибуты функциям

Отредактировано Shaman (Май 22, 2014 12:11:53)

Офлайн

#3 Май 22, 2014 12:12:23

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

Я не очень понял, что нужно, но возможно Вам поможет такой хак: функция, это собственно тоже объект, можете назначать ей любые атрибуты

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



Офлайн

#4 Май 22, 2014 12:40:54

gingray
Зарегистрирован: 2014-05-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

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)

Офлайн

#5 Май 22, 2014 14:24:30

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

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
>>> 

Офлайн

#6 Май 22, 2014 16:13:53

gingray
Зарегистрирован: 2014-05-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Декоратор, который возвращет два значения

Спасибо думаю то что нужно, еще осваиваюсь с Python'ом! Зачет.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version