2014-04-16 4 views
3

J'ai créé un objet appelé 'Frame'mise en cache Python dans les objets

class Frame: 
    def __init__(self, image): 
     self.image = image 

    def gray(self): 
     return cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 

Certaines opérations, par exemple gris(), sont chers. Je voudrais mettre en cache le résultat dans l'instance afin que les appels ultérieurs n'aient pas à recalculer cela. Quelle est la façon la plus propre de le faire?

Répondre

3

Pyramid utilise this fantastic @reify decorator:

class reify(object): 
    """ Use as a class method decorator. It operates almost exactly like the 
    Python ``@property`` decorator, but it puts the result of the method it 
    decorates into the instance dict after the first call, effectively 
    replacing the function it decorates with an instance variable. It is, in 
    Python parlance, a non-data descriptor. An example: 

    .. code-block:: python 

     class Foo(object): 
      @reify 
      def jammy(self): 
       print('jammy called') 
       return 1 

    And usage of Foo: 

    >>> f = Foo() 
    >>> v = f.jammy 
    'jammy called' 
    >>> print(v) 
    1 
    >>> f.jammy 
    1 
    >>> # jammy func not called the second time; it replaced itself with 1 
    """ 
    def __init__(self, wrapped): 
     self.wrapped = wrapped 
     try: 
      self.__doc__ = wrapped.__doc__ 
     except: # pragma: no cover 
      pass 

    def __get__(self, inst, objtype=None): 
     if inst is None: 
      return self 
     val = self.wrapped(inst) 
     setattr(inst, self.wrapped.__name__, val) 
     return val 

Le docstring parle pour lui-même. =)

+0

drôle comment la déclaration de méthode devient membre. tout à fait contre-intuitif, je trouverais. (encore, réponse assez soignée) – njzk2

+0

@ njzk2: Eh bien, son intention est d'être comme @ propriété. – Ryan

+0

Et si les valeurs changent? Sont-ils sujets à changement? –

0

Cela ne peut-il pas simplement être fait sur instanciation?

class Frame: 
    def __init__(self, image): 
     self.image = image 
     self.gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 

EDIT - Cela semble être un bon moment pour une propriété?

class Frame(object): 
    def __init__(self, image): 
     self.image = image 
     self._grey = None 

    @property 
    def grey(self): 
     if self._grey is None: 
      self._grey = solve_for_grey(self.image, stuff) 
     return self._grey 
+2

Parce que c'est cher ... Et peut-être pas nécessaire. –

+0

Je vois. Ok alors –