Décorateur de propriétés [Révisé] qui met en cache les valeurs

Réécrivez l'extrait que j'ai écrit plus tôt. Une fois lu, la propriété sera conservée jusqu'à ce que l'objet soit détruit. C'est la spécification.

Vous pouvez également écrire pour utiliser un cache approprié en spécifiant un backend de trésorerie pour la variable décorateur. Faisons-le plus tard

dec.py


from functools import wraps
import mox
from unittest import TestCase

def cached_property(f):
    prefix = '_cached_property_'
    @wraps(f)
    def _cached_property(self):
        key = prefix + f.__name__
        if hasattr(self, key):
            return getattr(self, key)
        value = f(self)
        setattr(self, key, value)
        return value
    return property(_cached_property)


class TestCachedProperty(TestCase):
    def setUp(self):
        self.m = mox.Mox()

    def tearDown(self):
        self.m.UnsetStubs()
        self.m = None

    def test_call_1(self):
        """Simple call."""

        # Procuder function that should be called twice.
        producer = self.m.CreateMockAnything()
        producer().AndReturn(30)
        producer().AndReturn(101)
        producer().AndReturn(None)
        producer().AndReturn(0)
        producer().AndReturn('')

        class C(object):
            @cached_property
            def f(self):
                return producer()

        # Try
        self.m.ReplayAll()
        c = C()
        c2 = C()
        c3 = C()
        c4 = C()
        c5 = C()

        # Verify
        self.assertEqual(c.f, 30)
        self.assertEqual(c.f, 30)
        self.assertEqual(c._cached_property_f, 30)
        self.assertEqual(c2.f, 101)
        self.assertEqual(c2.f, 101)
        self.assertEqual(c2._cached_property_f, 101)
        self.assertEqual(c3.f, None)
        self.assertEqual(c3.f, None)
        self.assertEqual(c3._cached_property_f, None)
        self.assertEqual(c4.f, 0)
        self.assertEqual(c4.f, 0)
        self.assertEqual(c4._cached_property_f, 0)
        self.assertEqual(c5.f, '')
        self.assertEqual(c5.f, '')
        self.assertEqual(c5._cached_property_f, '')
        self.m.VerifyAll()

        return

    def test_call_2(self):
        """Check that property function reference self."""

        # Procuder function that should be called once.
        producer = self.m.CreateMockAnything()
        producer().AndReturn(30)
        producer().AndReturn(101)

        class C(object):
            @cached_property
            def f(self):
                return self.g()
            def g(self):
                return producer()

        # Try
        self.m.ReplayAll()
        c = C()
        c2 = C()

        # Verify
        self.assertEqual(c.f, 30)
        self.assertEqual(c.f, 30)
        self.assertEqual(c._cached_property_f, 30)
        self.assertEqual(c2.f, 101)
        self.assertEqual(c2.f, 101)
        self.assertEqual(c2._cached_property_f, 101)
        self.m.VerifyAll()

        return

Recommended Posts

Décorateur de propriétés [Révisé] qui met en cache les valeurs
Résumez le décorateur @property de Python
Utilisez Property Decorator?