Уведомления

Группа в Telegram: @pythonsu

#1 Май 6, 2017 11:27:41

nickmetal
Зарегистрирован: 2012-11-15
Сообщения: 49
Репутация: +  0  -
Профиль   Отправить e-mail  

Как работает setattr?

Сразу напишу, что вопрос не в том,как мне поступить в этой ситуации, а понять, почему setattr ведёт себя так
Я знаю, что стандартный логгер можно использовать так, как я это пытаюсь сделать в этом классе.
Суть проблемы в том, что, когда я запускаю этот скрипт(это я его написал), то print в любом случае для level мне выводит
"error"(т.е. последнее значение из списка, по которому я прохожусь в методе _init_log_level_attributes ). Пробую на Python3.5. В методе закомментировал способ, при котором оно работает, но это ж явно не Python-way.

 import logging
class FileLogger():
    def __init__(self, path, **kwargs):
        self.logger = self.get_file_logger()
        self._init_log_level_attributes()
    def get_file_logger(self):
        return logging.getLogger(self.name)
    def _init_log_level_attributes(self):
        # так НЕ работает
        for level in ['info', 'warning', 'error']:
            setattr(self, level, lambda *args: self.log(*args, level=level))
        # так работает
        # setattr(self, 'info', lambda *args: self.log(*args, level='info'))
        # setattr(self, 'warning', lambda *args: self.log(*args, level='warning'))
        # setattr(self, 'error', lambda *args: self.log(*args, level='error'))
    def log(self, *args, **kwargs):
        text = " ".join(str(string) for string in args)
        if self.is_enable_stdout:
            print(text, kwargs['level'])
        self.logger.__getattribute__(kwargs['level'])(text)
if __name__ == '__main__':
    # цель logger.'level'(), а не logger.logger.'level'()
    logger = FileLogger('path.log')
    logger.info(text1, text1, ...)
    logger.error(text1, text1, ...)
    logger.warning(text1, text1, ...)

Отредактировано nickmetal (Май 6, 2017 11:28:28)

Офлайн

#2 Май 6, 2017 13:36:43

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Как работает setattr?

 lambda level=level, *args: self.log(*args, level=level)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Май 6, 2017 23:15:41

nickmetal
Зарегистрирован: 2012-11-15
Сообщения: 49
Репутация: +  0  -
Профиль   Отправить e-mail  

Как работает setattr?

нет, так не работает, если я вызываю как logger.info(text1, text2, …), то будет ошибка, что слишком много передано аргументов.

Офлайн

#4 Май 6, 2017 23:50:52

nickmetal
Зарегистрирован: 2012-11-15
Сообщения: 49
Репутация: +  0  -
Профиль   Отправить e-mail  

Как работает setattr?

нет, так не работает, если я вызываю как logger.info(text1, text2, …), то будет ошибка, что слишком много передано аргументов.


все-таки хотелось бы узнать про причины такого неявного поведения функции setattr
Саму код я заменил на такой вариант, чтобы работало

 from functools import partial
def _init_log_level_attributes(self):
    for level in['info', 'warning', 'error']:
        setattr(self, level, partial(self.log, level=level))

Отредактировано nickmetal (Май 6, 2017 23:52:20)

Офлайн

#5 Май 8, 2017 16:21:59

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Как работает setattr?

> все-таки хотелось бы узнать про причины такого неявного поведения функции setattr

setattr работает как надо. Замыкание передаёт в функцию ссылку значение которой постоянно меняется.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version