How to set a max length for a python list/set?

2019-04-18 13:01发布

问题:

In c/c++, we could have:

maxnum = 10;
double xlist[maxnum];

How to set a maximum length for a python list/set?

回答1:

You don't and do not need to.

Python lists grow and shrink dynamically as needed to fit their contents. Sets are implemented as a hash table, and like Python dictionaries grow and shrink dynamically as needed to fit their contents.

Perhaps you were looking for collections.deque (which takes a maxlen parameter) or something using a heapq (using heapq.heappushpop() when you have reached the maximum) instead?



回答2:

Here is extended version of python's list. It behaves like list, but will raise BoundExceedError, if length is exceeded (tried in python 2.7):

class BoundExceedError(Exception):
    pass


class BoundList(list):
    def __init__(self, *args, **kwargs):
        self.length = kwargs.pop('length', None)
        super(BoundList, self).__init__(*args, **kwargs)

    def _check_item_bound(self):
        if self.length and len(self) >= self.length:
            raise BoundExceedError()

    def _check_list_bound(self, L):
        if self.length and len(self) + len(L) > self.length:
            raise BoundExceedError()

    def append(self, x):
        self._check_item_bound()
        return super(BoundList, self).append(x)

    def extend(self, L):
        self._check_list_bound(L)
        return super(BoundList, self).extend(L)

    def insert(self, i, x):
        self._check_item_bound()
        return super(BoundList, self).insert(i, x)

    def __add__(self, L):
        self._check_list_bound(L)
        return super(BoundList, self).__add__(L)

    def __iadd__(self, L):
        self._check_list_bound(L)
        return super(BoundList, self).__iadd__(L)

    def __setslice__(self, *args, **kwargs):
        if len(args) > 2 and self.length:
            left, right, L = args[0], args[1], args[2]
            if right > self.length:
                if left + len(L) > self.length:
                    raise BoundExceedError()
            else:
                len_del = (right - left)
                len_add = len(L)
                if len(self) - len_del + len_add > self.length:
                    raise BoundExceedError()
        return super(BoundList, self).__setslice__(*args, **kwargs)

Usage:

>>> l = BoundList(length=10)
>>> l.extend([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> # now all these attempts will raise BoundExceedError:
>>> l.append(11)
>>> l.insert(0, 11)
>>> l.extend([11])
>>> l += [11]
>>> l + [11]
>>> l[len(l):] = [11]


回答3:

Once you have your list, lst, you can

if len(lst)>10:
    lst = lst[:10]

If size more than 10 elements, you truncate to first ten elements.



回答4:

You can't, lists and sets are dynamic in nature and can grow to any size.

Python is not c++, python is a dynamic language. Sets and list can expand or shrink to any size.

Use heapq module if you want x smallest or largest items from an iterable.

heapq.nsmallest(n, iterable[, key])

Return a list with the n smallest elements from the dataset defined by iterable. key, if provided, specifies a function of one argument that is used to extract a comparison key from each element in the iterable: key=str.lower Equivalent to: sorted(iterable, key=key)[:n]

Or may be bisect module:

This module provides support for maintaining a list in sorted order without having to sort the list after each insertion.

Then use slicing or itertools.slice to get top x items from the list.