Форум сайта python.su
0
Сразу напишу, что вопрос не в том,как мне поступить в этой ситуации, а понять, почему 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)
Офлайн
186
lambda level=level, *args: self.log(*args, level=level)
Офлайн
0
нет, так не работает, если я вызываю как logger.info(text1, text2, …), то будет ошибка, что слишком много передано аргументов.
Офлайн
0
нет, так не работает, если я вызываю как 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)
Офлайн
186
> все-таки хотелось бы узнать про причины такого неявного поведения функции setattr
setattr работает как надо. Замыкание передаёт в функцию ссылку значение которой постоянно меняется.
Офлайн