Найти - Пользователи
Полная версия: Декоратор, который возвращет два значения
Начало » Python для новичков » Декоратор, который возвращет два значения
1
gingray
Всем день добрый, захотелось не много странного. Можно ли сделать декоратор который бы возвращал, помимо декорируемой функции, дополнительный объект, при этом для кода, который бы вызывал функцию, продолжал думать что это функция.
Хотел возвращать объект который может вести себя как функция, но что - то не срослось. Задача стоит в профилировании тире логировании методов вот пример кода того что хотел сделать но не вышло.
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)
Shaman
То есть там где ожидается функция будет список, со всеми проистекающими.
  • можно вернуть callable object
  • можно заполнять внешнюю по отношению к функции и декоратору структуру доп. атрибутов
  • можно назначать доп. атрибуты функциям
FishHook
Я не очень понял, что нужно, но возможно Вам поможет такой хак: функция, это собственно тоже объект, можете назначать ей любые атрибуты
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
gingray
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)
Хотел бы получить такую штуку, возможно ли так сделать ?
Shaman
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
>>> 
gingray
Спасибо думаю то что нужно, еще осваиваюсь с Python'ом! Зачет.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB