Snippet List
Python's [descriptor][1] protocol can seem a bit esoteric at first; however, it can
be invaluable in handling everyday idioms and patterns - something that the
Django framework authors have taken advantage of in numerous occasions
(e.g.: [auth middleware][2]).
One such idiom I see and use often and would like to generalize is the
attribute-existence check-or-set routine illustrated here:
def get_foo(self):
if not hasattr(self, '_foo'):
self._foo = init_foo()
return self._foo
Rather than coding this up multiple times (either for a given class or across
many unrelated classes), I would prefer to delegate this repetitive work to a
descriptor and remain [DRY][3]. The means to this end is implemented as a
variation on the Python `property` construct, and is intentionally over simplistic
(I leave the details of the heavy lifting up to the reader).
The basic premise shown in source here is simply straight-forward Python, a
quick and dirty example of how it could be utilized within a Django context is
shown here:
from django.db import models
from cacheprop import CacheProperty2
ARTIFACT_TYPES = (
('F', _('File')),
('D', _('Directory')),
('A', _('Alias')),
)
class Artifact(models.Model):
# model fields
name = models.CharField(maxlength=64)
type = models.CharField(maxlength=1, choices=ARTIFACT_TYPES)
file_metadata = CacheProperty2(
lambda self: self.filemetadata_set.get(artifact__id=self.id)
)
class FileMetadata(models.Model):
byte_size = models.IntegerField()
artifact = models.ForeignKey(Artifact, unique=True)
[1]: http://users.rcn.com/python/download/Descriptor.htm
[2]: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/middleware.py
[3]: http://c2.com/cgi/wiki?DontRepeatYourself
2 snippets posted so far.