Python, заставляя список фиксированному размеру

В Python (3) Я хочу создать список, содержащий последние 5 переменных, введенных в него. Вот пример:

>>>l = []
>>>l.append('apple')
>>>l.append('orange')
>>>l.append('grape')
>>>l.append('banana')
>>>l.append('mango')
>>>print(l)
['apple','orange','grape','banana','mango']
>>>l.append('kiwi')
>>>print(l)
['orange','grape','banana','mango','kiwi'] #only 5 items in list

Итак, в python: Есть ли способ достичь того, что продемонстрировано выше? Переменная не обязательно должна быть списком, я просто использовал ее в качестве примера.

Спасибо!

Ответ 1

Вместо этого вы можете использовать объект collection.deque с аргументом конструктора maxlen:

>>>l = collections.deque(maxlen=5)
>>>l.append('apple')
>>>l.append('orange')
>>>l.append('grape')
>>>l.append('banana')
>>>l.append('mango')
>>>print(l)
deque(['apple','orange','grape','banana','mango'], maxlen=5)
>>>l.append('kiwi')
>>>print(l)
deque(['orange','grape','banana','mango','kiwi'], maxlen=5) #only 5 items in list

Ответ 2

Вы можете подклассом list

>>> class L(list):
...     def append(self, item):
...         list.append(self, item)
...         if len(self) > 5: self[:1]=[]
... 
>>> l = L()
>>> l.append('apple')
>>> l.append('orange')
>>> l.append('grape')
>>> l.append('banana')
>>> l.append('mango')
>>> print(l)
['apple', 'orange', 'grape', 'banana', 'mango']
>>> l.append('kiwi')
>>> print(l)
['orange', 'grape', 'banana', 'mango', 'kiwi']
>>> 

Ответ 3

Я столкнулся с этой проблемой... maxlen = 5 из deque не был поддерживаемой опцией из-за проблем с доступом/надежностью доступа.

ПРОСТОЕ решение:

l = []
l.append(x)                         # add 'x' to right side of list
l = l[-5:]                          # maxlen=5

После добавления, просто переопределите 'l' как последние пять элементов 'l'.

print(l)

Назовите его Готово.

Для ваших целей вы можете остановиться прямо там... но мне нужен popleft(). Если pop() удаляет элемент справа, где он был просто добавлен... pop (0) удаляет его слева:

if len(l) == 5:                     # if the length of list 'l' has reached 5 
    right_in_left_out = l.pop(0)    # l.popleft()
else:                               #
    right_in_left_out = None        # return 'None' if not fully populated

Кончик шляпы Джеймсу на Tradewave.net

Нет необходимости в функциях класса или deque.

Далее... для добавления влево и вправо:

l = []
l.insert(0, x)                      # l.appendleft(x)
l = l[-5:]                          # maxlen=5

Был бы ваш эквивалент appendleft(), если вы хотите, чтобы вы загружали свой список, не используя deque

Наконец, если вы решите добавить слева...

if len(l) == 5:                     # if the length of list 'l' has reached 5 
    left_in_right_out = l.pop()     # pop() from right side
else:                               #
    left_in_right_out = None        # return 'None' if not fully populated

Ответ 4

deque медленный для случайного доступа и не поддерживает нарезку. Следуя предложению gnibbler, я собрал полный подкласс list.

Однако он предназначен для "рулона" только справа налево. Например, insert() в "полном" списке не будет иметь эффекта.

class LimitedList(list):

    # Read-only
    @property
    def maxLen(self):
        return self._maxLen

    def __init__(self, *args, **kwargs):
        self._maxLen = kwargs.pop("maxLen")
        list.__init__(self, *args, **kwargs)

    def _truncate(self):
        """Called by various methods to reinforce the maximum length."""
        dif = len(self)-self._maxLen
        if dif > 0:
            self[:dif]=[]

    def append(self, x):
        list.append(self, x)
        self._truncate()

    def insert(self, *args):
        list.insert(self, *args)
        self._truncate()

    def extend(self, x):
        list.extend(self, x)
        self._truncate()

    def __setitem__(self, *args):
        list.__setitem__(self, *args)
        self._truncate()

    def __setslice__(self, *args):
        list.__setslice__(self, *args)
        self._truncate()

Ответ 5

Вы можете использовать ограниченную коллекцию в PyMongo - она излишняя, но хорошо справляется со своей задачей:

import pymongo

#create collection
db.createCollection("my_capped_list",{capped:True, max:5})

#do inserts ...

#Read list
l = list(db.my_capped_list.find())

Следовательно, каждый раз, когда вы вызываете my_capped_list, вы извлекаете последние 5 вставленных элементов.

Ответ 6

Чаще всего, когда вам нужен такой объект, вы должны написать функцию, которая берет список, а затем возвращает последние пять элементов.

>>> l = range(10)
>>> l[-5:]

Но если вы действительно хотите создать собственный список, имея ограничение на пять элементов, вы можете переопределить встроенный список и его методы, вы бы сделали что-то подобное, для всех его методов.

class fivelist(list):
    def __init__(self, items):
        list.__init__(self, items[-5:])

    def insert(self, i, x):
        list.insert(self, i, x)
        return self[-5:]

    def __getitem__(self, i):
        if i > 4:
           raise IndexError
        return list.__getitem__(self, i)

    def __setitem__(self, i, x):
        if 0<= i <= 4:
          return list.__setitem__(self, i, x)
        else:
          raise IndexError

Ответ 7

Это может быть так же просто, как приведенное ниже решение

lst = []
arr_size = int(input("Enter the array size "))
while len(lst) != arr_size:
    arr_elem= int(input("Enter the array element "))
    lst.append(arr_elem)

sum_of_elements = sum(lst)

print("Sum is {0}".format(sum_of_elements))