How to instantiate in a lazy way?
Nick Craig-Wood
nick at craig-wood.com
Mon Dec 1 10:30:44 EST 2008
Slaunger <Slaunger at gmail.com> wrote:
> Slaunger wrote:
> >
> > class PayloadOnDemand(object):
> > ? ? """
> > ? ? Behaves as a PayloadInstant object, but instantiation is faster
> > ? ? as only the position of the payload in the file is stored
> > initially in the object.
> > ? ? Only when acessing the initially non-existing data attribute
> > ? ? are the data actually read and the attribure created and bound to
> > the instance.
> > ? ? This will actually be a little slower than in PayloadInstant as
> > the correct file position
> > ? ? has to be seeked out first.
> > ? ? On later calls the object has as efficient attribute access as
> > PayloadInstant
> > ? ? """
> >
> > ? ? @classmethod
> > ? ? def read_from_file(cls, f, size):
> > ? ? ? ? pos = f.tell()
> > ? ? ? ? f.seek(pos + size) #Skip to end of payload
> > ? ? ? ? return cls(pos)
>
> Extend with ref to file instead:
> return cls(f, pos)
> >
> > ? ? # I probably need some __getattr__ or __getattribute__ magic
> > # there...??
>
> To answer my own rethorical question I guess I should do something
> like this
>
> def __getattr__(self, attr_name):
> """
> Only called if attr_name is not in the __dict__ for the
> instance
> """
> if attr_name == 'data':
> self.__dict__[attr_name] = read_data(self.f,
> self.file_position)
>
> >
> > ? ? def __init__(self, a_file_position):
> > ? ? ? ? self.file_position = a_file_position
> >
> and then I need to also store a reference to the file in the
> constructor...
>
> def __init__(self, a_file, a_file_position):
> self.f = a_file
> self.file_position = a_file_position
>
> Have I understood correctly how to to it the on demand way?
I wouldn't use __getattr__ unless you've got lots of attributes to
overload. __getattr__ is a recipe for getting yourself into trouble
in my experience ;-)
Just do it like this...
class PayloadOnDemand(object):
def __init__(self, a_file, a_file_position):
self._data = None
self.f = a_file
self.file_position = a_file_position
@property
def data(self):
if self._data is None:
self._data = self.really_read_the_data()
return self._data
then you'll have a .data attribute which when you read it for the
first time it will populate itself.
If None is a valid value for data then make a sentinel, eg
class PayloadOnDemand(object):
sentinel = object()
def __init__(self, a_file, a_file_position):
self._data = self.sentinel
self.f = a_file
self.file_position = a_file_position
@property
def data(self):
if self._data is self.sentinel:
self._data = self.really_read_the_data()
return self._data
--
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick
More information about the Python-list
mailing list