python: are property fields being cached automatically?

后端 未结 8 718
离开以前
离开以前 2020-12-14 15:20

My question is are the following two pieces of code run the same by the interpreter:

class A(object):
  def __init__(self):
     self.__x = None

  @property         


        
8条回答
  •  情歌与酒
    2020-12-14 15:58

    Properties do not automatically cache their return values. The getter (and setters) are intended to be called each time the property is accessed.

    However, Denis Otkidach has written a wonderful cached attribute decorator (published in the Python Cookbook, 2nd edition and also originally on ActiveState under the PSF license) for just this purpose:

    class cache(object):    
        '''Computes attribute value and caches it in the instance.
        Python Cookbook (Denis Otkidach) https://stackoverflow.com/users/168352/denis-otkidach
        This decorator allows you to create a property which can be computed once and
        accessed many times. Sort of like memoization.
    
        '''
        def __init__(self, method, name=None):
            # record the unbound-method and the name
            self.method = method
            self.name = name or method.__name__
            self.__doc__ = method.__doc__
        def __get__(self, inst, cls):
            # self: <__main__.cache object at 0xb781340c>
            # inst: <__main__.Foo object at 0xb781348c>
            # cls:        
            if inst is None:
                # instance attribute accessed on class, return self
                # You get here if you write `Foo.bar`
                return self
            # compute, cache and return the instance's attribute value
            result = self.method(inst)
            # setattr redefines the instance's attribute so this doesn't get called again
            setattr(inst, self.name, result)
            return result
    

    Here is an example demonstrating its use:

    def demo_cache():
        class Foo(object):
            @cache
            def bar(self):
                print 'Calculating self.bar'  
                return 42
        foo=Foo()
        print(foo.bar)
        # Calculating self.bar
        # 42
        print(foo.bar)    
        # 42
        foo.bar=1
        print(foo.bar)
        # 1
        print(Foo.bar)
        # __get__ called with inst = None
        # <__main__.cache object at 0xb7709b4c>
    
        # Deleting `foo.bar` from `foo.__dict__` re-exposes the property defined in `Foo`.
        # Thus, calling `foo.bar` again recalculates the value again.
        del foo.bar
        print(foo.bar)
        # Calculating self.bar
        # 42
    
    demo_cache()
    

提交回复
热议问题