T
thebjorn
I seem to be writing the following boilerplate/pattern quite
frequently to avoid hitting the database until absolutely necessary,
and to only do it at most once:
class Foo(object):
@property
def expensive(self):
if not hasattr(self, '_expensiv'):
self._expensive = <insert expensive db call here>
return self._expensive
it's a bit verbose, and it violates the DRY (Don't Repeat Yourself)
principle -- and it has on at least one occasion resulted in really
slow code that produces the correct results (did you spot the typo
above?).
It would have been nice to be able to write
class Foo(object):
@property
def expensive(self):
self.expensive = <insert expensive db call here>
return self.expensive
but apparently I "can't set [that] attribute" :-(
I'm contemplating using a decorator to hide the first pattern:
def memprop(fn):
def _fn(self): # properties only take self
memname = '_' + fn.__name__
if not hasattr(self, memname):
setattr(self, memname, fn(self))
return getattr(self, memname)
return property(fget=_fn, doc=fn.__doc__)
which means I can very simply write
class Foo(object):
@memprop
def expensive(self):
return <insert expensive db call here>
I'm a bit hesitant to start planting home-grown memprop-s all over the
code-base though, so I'm wondering... does this seem like a reasonable
thing to do? Am I re-inventing the wheel? Is there a better way to
approach this problem?
-- bjorn
frequently to avoid hitting the database until absolutely necessary,
and to only do it at most once:
class Foo(object):
@property
def expensive(self):
if not hasattr(self, '_expensiv'):
self._expensive = <insert expensive db call here>
return self._expensive
it's a bit verbose, and it violates the DRY (Don't Repeat Yourself)
principle -- and it has on at least one occasion resulted in really
slow code that produces the correct results (did you spot the typo
above?).
It would have been nice to be able to write
class Foo(object):
@property
def expensive(self):
self.expensive = <insert expensive db call here>
return self.expensive
but apparently I "can't set [that] attribute" :-(
I'm contemplating using a decorator to hide the first pattern:
def memprop(fn):
def _fn(self): # properties only take self
memname = '_' + fn.__name__
if not hasattr(self, memname):
setattr(self, memname, fn(self))
return getattr(self, memname)
return property(fget=_fn, doc=fn.__doc__)
which means I can very simply write
class Foo(object):
@memprop
def expensive(self):
return <insert expensive db call here>
I'm a bit hesitant to start planting home-grown memprop-s all over the
code-base though, so I'm wondering... does this seem like a reasonable
thing to do? Am I re-inventing the wheel? Is there a better way to
approach this problem?
-- bjorn