Страницы

Поиск по вопросам

суббота, 8 февраля 2020 г.

Как обернуть функцию декоратором?

#python #python_32 #декоратор


Есть функция

def startInvRej(self, event): 
    if 2 < event.button < 4:
        self.canvCoor = []
        self.frameCoor = []
        print(event.x)
        print(event.xdata)
        self.frameCoor.append(event.x)
        self.canvCoor.append(float(event.xdata))
        print(self.frameCoor)
        print(self.canvCoor)


Как завернуть ее в декоратор, чтобы функция выполнялась с отладочным выводом (т.е.
с print'ами), если это необходимо, а иначе без него?



После Ваших ответов и недолгих раздумий было решено сделать таким образом: 

def decorator(func):
    def wrapped(self, event):
        print(event.x)
        print(event.xdata)
        func(self, event)
        print(self.frameCoor)
        print(self.canvCoor)
    return wrapped

@decorator
def startInvRej(self, event):
    if event.button ==3:
        self.canvCoor = []
        self.frameCoor = []
        self.frameCoor.append(event.x)
        self.canvCoor.append(float(event.xdata))


Насколько этот способ корректен? И объясните, пожалуйста, почему такой способ работает
несмотря на то, что я написал func(self, event), а не startInvRej(self, event)?
    


Ответы

Ответ 1



Прежде всего, рекомендую перейти на Python 3.3. Зачем быть не в тренде? Далее, не могу не порекомендовать встроенный модуль logging Пример из HOWTO: import logging logging.basicConfig(filename='example.log',level=logging.DEBUG) logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too') Выведет в указанный файл: DEBUG:root:This message should go to the log file INFO:root:So should this WARNING:root:And this, too Запускаете своё приложение с ключом --log=INFO и наслажлаетесь фильтрованным логированием. Если задача именно в освоении декораторов, можно сделать супер-тупо: # Заглушка, которая не выводит ничего def log_print_stub( *args, **kwargs ): pass # глобальная переменная, с помощью которой # вызывается либо функция print для логгирования, # либо log_print_stub, чтобы ничего не делать log_print = log_print_stub # декоратор, изменяющий состояние глобальной переменной # перед вызовом декорируемой функции def logged(fn): def wrapped(*args, **kwargs): global log_print log_print = print result = fn(*args, **kwargs) log_print = log_print_stub return result return wrapped # пример: @logged def show_log( message ): print( "show_log" ) log_print( message, " ", message ) def dont_show_log( message ): print( "dont_show_log") log_print( message, " ", message ) # декорированная функция выведет "Видно Видно" show_log( "Видно" ) # не декорированная ничего дополнительно не делает dont_show_log( "Не видно" ) Считаю этот метод супер-тупым, так как глобальные переменные - зло. Кроме того, теоретически, этот метод непотокобезопасен.

Ответ 2



Если честно, тут очевидного применения декоратора я не вижу, может потому что не так часто ими пользуюсь, но всё же. А почему бы не попробовать вот так: def startInvRej(self, event, debug=False): if 2 < event.button < 4: self.canvCoor = [] self.frameCoor = [] if debug: print(event.x) print(event.xdata) self.frameCoor.append(event.x) self.canvCoor.append(float(event.xdata)) if debug: print(self.frameCoor) print(self.canvCoor) Там ведь достаточно очевидно и просто всё выглядит :)

Комментариев нет:

Отправить комментарий