Python list устанавливает значение в индексе, если индекс не существует

есть ли способ, lib или что-то в python, что я могу установить значение в списке по индексу, который не существует? Что-то вроде создания индекса времени выполнения в списке:

l = []
l[3] = 'foo'
# [None, None, None, 'foo']

и более далее, с многомерными списками:

l = []
l[0][2] = 'bar'
# [[None, None, 'bar']]

или с существующего:

l = [['xx']]
l[0][1] = 'yy'
# [['xx', 'yy']]

4 ответов


нет встроенного, но его достаточно легко реализовать:

class FillList(list):
    def __setitem__(self, index, value):
        try:
            super().__setitem__(index, value)
        except IndexError:
            for _ in range(index-len(self)+1):
                self.append(None)
            super().__setitem__(index, value)

или, если вам нужно изменить существующие списки ванили:

def set_list(l, i, v):
      try:
          l[i] = v
      except IndexError:
          for _ in range(i-len(l)+1):
              l.append(None)
          l[i] = v

вы не можете создать список с пробелами. Вы могли бы использовать dict или этот быстрый маленький парень:

def set_list(i,v):
    l = []
    x = 0
    while x < i:
        l.append(None)
        x += 1
    l.append(v)
    return l

print set_list(3, 'foo')
>>> [None, None, None, 'foo']

если вы действительно хотите синтаксис в вашем вопросе, defaultdict вероятно, лучший способ получить его:

from collections import defaultdict
def rec_dd(): 
    return defaultdict(rec_dd)

l = rec_dd()
l[3] = 'foo'

print l
{3: 'foo'}

l = rec_dd()
l[0][2] = 'xx'
l[1][0] = 'yy'
print l
<long output because of defaultdict, but essentially)
{0: {2: 'xx'}, 1: {0: 'yy'}}

это не совсем "список списков", но он работает более или менее как один.

вам действительно нужно указать вариант использования... выше имеет некоторые преимущества (вы можете получить доступ к индексам, не проверяя, существуют ли они в первую очередь), так и некоторые недостатки - например, l[2] в нормальном dict вернет KeyError, но в defaultdict Он просто создает пустой defaultdict, добавляет его, а затем возвращает его.

другие возможные реализации для поддержки различных синтаксических сахаров могут включать пользовательские классы и т. д., и будут иметь другие компромиссы.


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

l = [None for i in some_large_number]
l[3] = 'foo'
# [None, None, None, 'foo', None, None None ... ]