替换实例方法

时间:2012-02-05 03:56:46

标签: python class methods attributes instance

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 个答案:

答案 0 :(得分:3)

我认为这里的基本想法是正确的,有一些小的修正。首先,

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更快。