Как работает присвоение @property? (Присвоение геттера другой переменной.) - PullRequest
2 голосов
/ 05 сентября 2011

У меня есть такой код:

class Debug(object):
  ...

  @property
  def ThreadAwareLogger(self):
    if not self.logger_instance_for_current_thread:
      self.logger_instance_for_current_thread=self.cloneMainLogger()
    return self.logger_instance_for_current_thread

  def cloneMainLogger(self):
    return logger_instance_for_current_thread

class SomeOtherClass(object):

  def __init__(self):
    ...
    self.logger=debug.ThreadAwareLogger

  def otherMethod(self):
    ...
    self.logger.info("Message")

Проблематичным является задание self.logger=debug.ThreadAwareLogger. Я не уверен, что будет удовлетворено self.logger. Я хочу, чтобы это был весь получатель, и я хочу, чтобы получатель выполнялся каждый раз, когда я использую self.logger в SomeOtherClass. Но я боюсь, что в self.logger будет храниться только результат получения logger_instance_for_current_thread. Это означает регистратор потока, который был активен во время назначения. Этот регистратор не обязательно должен быть правильным, когда я звоню self.logger.info("Message").

Как заставить получатель ThreadAwareLogger выполняться каждый раз, когда я звоню self.logger.info("Message")?

Sidenote: Зачем мне на самом деле нужен ярлык self.logger? Когда я решу заменить ThreadAwareLogger на AdvancedThreadAwareLogger, я поменяю только одно назначение вместо тысячи вызовов self.logger.info("Message"). Кроме того, otherMethod не заботится о том, какой регистратор будет использоваться.

Edit:

Назначение геттера работает, как описано в ответе @unutbu. Но назначение получателя вызывает проблему, о которой я раньше не думал.

Из ThreadAwareLogger я на самом деле вызываю метод cloneMainLogger. Теперь вызов someOtherClass.logger заканчивается исключением: AttributeError: у объекта SomeOtherClass нет атрибута cloneMainLogger.

Пока что я обошел проблему с небольшим взломом. SomeOtherClass на самом деле имеет Debug экземпляр. Поэтому я звоню debug.cloneMainLogger() вместо self.cloneMainLogger() внутри ThreadAwareLogger. Программа сейчас работает, но я считаю ее действительно грязной.

Редактировать 2:

Если я добавлю строку self.comptreeLogger=Debug.ThreaAwareLogger внутри метода; например cloneMainLogger Я получаю AttributeError: у объекта 'property' нет атрибута 'debug'. Вывод: я до сих пор не понимаю решение.

Ответы [ 3 ]

2 голосов
/ 05 сентября 2011

Один из способов получить целое свойство - просто создать другое свойство:

class SomeOtherClass:

    @property
    def logger(self):
        return self.debug.ThreadAwareLogger

Могут быть и другие пути.

1 голос
/ 05 сентября 2011
import logging
import random

class Debug(object):
    @property
    def ThreadAwareLogger(self):
        loggers = [logging.getLogger('abc'),logging.getLogger('def')]
        return self.anotherDebugMethod(loggers)
    def anotherDebugMethod(self,loggers):
        return random.choice(loggers)
class SomeOtherClass(object):
    def __init__(self):
        self.debug=Debug()
    @property
    def logger(self):
        return self.debug.ThreadAwareLogger
    def otherMethod(self):
        self.logger.info('Message')

if __name__=='__main__':
    logging.basicConfig(level=logging.DEBUG)    
    x=SomeOtherClass()
    for i in range(5):
        x.otherMethod()

дает вывод, например:

INFO:def:Message
INFO:abc:Message
INFO:def:Message
INFO:def:Message
INFO:abc:Message

Обратите внимание на изменения в abc и def показывают, что функция Debug.ThreadAwareLogger вызывается каждый раз.

1 голос
/ 05 сентября 2011

self.logger будет ссылаться на то, что возвращается свойством ThreadAwareLogger, а не на само свойство.

...