замена метода экземпляра - PullRequest
       21

замена метода экземпляра

2 голосов
/ 05 февраля 2012
class A:
  def f(self):
    print('f')
  def g(self):
    print('g')
  def h(self):
    print('h')

x = A()
y = A()
x.f = x.g # creates a new attribute 'f' for x
x.f() # 'g'; resolves at the instance attribute level to call instance method 'g'
y.f() # 'f'; instance methods are unaffected
A.f = A.h # redefines instance method 'f' to print 'h'
x.f() # 'g'; still resolves at the attribute level to call instance method 'g'
y.f() # 'h'; instance method 'f' now prints 'h'
A.g = A.h # redefines instance method 'g' to print 'h'
x.f() # 'g'; still calls the old instance method 'g' because it kept the link to it
y.f() # 'h'

Правильно ли мое понимание?

Я пытаюсь использовать это следующим образом:

  class Attributes:
    def __init__(self, params, cache_field = None):
      # ...
      self.cache_field = cache_field
      if cache_field is None:
        # I hope I'm setting instance attribute only
        self.check_cache = self.check_external_cache
      else:
        self.check_cache = self.check_internal_cache
        self.internal_cache = {}

    def check_internal_cache(self, record):
      return self.internal_cache[record.id]

    def check_external_cache(self, record):
      return record[self.cache_field]

    def calculate_attributes(self, record):
      try:
        return self.check_cache(record) # I hope it will resolve to instance attribute
      except KeyError:
        # calculate and cache the value here
        # ...

Будет ли это работать правильно? Это нормально делать это? Первоначально я надеялся сэкономить время по сравнению с проверкой self.cache_field в каждом звонке на calculate_attributes; но я больше не уверен, что это сэкономит время.

1 Ответ

3 голосов
/ 05 февраля 2012

Я думаю, что основная идея здесь верна, с парой небольших исправлений. Во-первых,

A.f = A.h # redefines instance method 'f' to print 'h'

Это должно читать class метод, а не метод экземпляра. Вы меняете класс здесь. И во-вторых, это не соответствует какой-либо определенной переменной здесь:

    if cache is None:

Я думаю, может быть, вы имеете в виду cache_field?

Как правило, установка атрибутов экземпляра в __init__ является совершенно нормальной и приемлемой. Неважно, что это метод, а не какой-то другой объект - он ничем не отличается от высказывания self.foo = 'bar'.

Кроме того, иногда это зависит, но в общем случае действительно быстрее установить метод в init, чем проверять cache_field каждый раз, когда вызывается check_cache.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...