Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python lazy list

Tags:

python

I would like create my own collection that has all the attributes of python list and also knows how to save/load itself into/from a database. Also I want to make the load implicit and lazy, as in it doesn't happen at the point of creation of the list, but waits until its first used.

Is there a single__xxx__method I can override to load the list on first usage of any list property (such aslen,getitem,iter...etc) without having to override them all?

like image 535
Kozyarchuk Avatar asked Oct 27 '08 19:10

Kozyarchuk


People also ask

What is a lazy list in Python?

A lazy list is an iterator that behaves like a list and possesses a cache mechanism. A lazy list is potentially infinite and speed performances of the cache is comparable with Python lists. One major difference with original Python list is that lazy list are immutable.

Are list comprehensions lazy?

The second big difference between list comprehension and generator expressions is that the latter has lazy evaluation. In this example you can see that once we assign to list comprehension to a variable the sqr function is called on each element.

Why Python is lazy?

The range method in Python follows the concept of Lazy Evaluation. It saves the execution time for larger ranges and we never require all the values at a time, so it saves memory consumption as well.


1 Answers

Not a single, but 5 is enough:

from collections import MutableSequence

class Monitored(MutableSequence):
    def __init__(self):
        super(Monitored, self).__init__()
        self._list = []

    def __len__(self):
        r = len(self._list)
        print "len: {0:d}".format(r)
        return r

    def __getitem__(self, index):
        r = self._list[index]
        print "getitem: {0!s}".format(index)
        return r

    def __setitem__(self, index, value):
        print "setitem {0!s}: {1:s}".format(index, repr(value))
        self._list[index] = value

    def __delitem__(self, index):
        print "delitem: {0!s}".format(index)
        del self._list[index]

    def insert(self, index, value):
        print "insert at {0:d}: {1:s}".format(index, repr(value))
        self._list.insert(index, value)

The correct way of checking if something implements the whole list interface is to check if it is a subclass of MutableSequence. The ABCs found in the collections module, of which MutableSequence is one, are there for two reasons:

  1. to allow you to make your own classes emulating internal container types so that they are usable everywhere a normal built-in is.

  2. to use as argument for isinstance and issubclass to verify that an object implements the necessary functionality:

>>> isinstance([], MutableSequence)
True
>>> issubclass(list, MutableSequence)
True

Our Monitored class works like this:

>>> m = Monitored()
>>> m.append(3)
len: 0
insert at 0: 3
>>> m.extend((1, 4))
len: 1
insert at 1: 1
len: 2
insert at 2: 4
>>> m.l
[3, 1, 4]
>>> m.remove(4)
getitem: 0
getitem: 1
getitem: 2
delitem: 2
>>> m.pop(0)   # after this, m.l == [1]
getitem: 0
delitem: 0
3
>>> m.insert(0, 4)
insert at 0: 4
>>> m.reverse()   # After reversing, m.l == [1, 4]
len: 2
getitem: 1
getitem: 0
setitem 0: 1
setitem 1: 4
>>> m.index(4)
getitem: 0
getitem: 1
1
like image 73
Lauritz V. Thaulow Avatar answered Sep 28 '22 08:09

Lauritz V. Thaulow