Найти - Пользователи
Полная версия: Как работает setattr?
Начало » Python для новичков » Как работает setattr?
1
nickmetal
Сразу напишу, что вопрос не в том,как мне поступить в этой ситуации, а понять, почему 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, ...)
Rodegast
 lambda level=level, *args: self.log(*args, level=level)
nickmetal
нет, так не работает, если я вызываю как logger.info(text1, text2, …), то будет ошибка, что слишком много передано аргументов.
nickmetal
нет, так не работает, если я вызываю как 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))
Rodegast
> все-таки хотелось бы узнать про причины такого неявного поведения функции setattr

setattr работает как надо. Замыкание передаёт в функцию ссылку значение которой постоянно меняется.
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