Как указать указать список ? Получение предметов не в последовательности

Я не уверен в этом методе. Я хочу создать список, где, если я попытаюсь получить доступ к элементу вне диапазона списка, список будет «зацикливаться». Пример поведения, которого я хочу достичь:

>>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] >>> musical_scale[2] E >>> musical_scale[7] C >>> musical_scale[-1] B 

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

4 Solutions collect form web for “Как указать указать список ? Получение предметов не в последовательности”

Используйте оператор модуля % для «возврата назад» после индексирования за конец списка

 >>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] def getValue(x, l): return l[x % len(l)] >>> getValue(0, musical_scale) 'C' >>> getValue(9, musical_scale) 'E' 

Создание подкласса List будет довольно полезным способом сделать это. Что-то вроде этого, возможно:

 class modList(list): def __getitem__(self, i): if len(self) == 0: raise IndexError # Or do something else if you want, like return [] i = i % len(self) # self.__len__() works also return super(modList, self).__getitem__(i) # In Python 3, super().__getitem__(i) 

Если вы хотите сделать нарезку, это немного сложнее, но похоже. Обнаружено это при просмотре StackOverflow:

  def __getitem__(self, i): if isinstance(i, int): if len(self) == 0: raise IndexError i = i % len(self) return super(modList, self).__getitem__(i) # list.__getitem__(i) works too elif isinstance(i, slice): if len(self) == 0: return [] start = i.start % len(self) stop = i.stop % len(self) step = i.step return super(modList, self).__getItem__(slice(start, stop, step)) else: raise TypeError("invalid index") 

Хотя эта модификация среза может дать вам такую ​​ситуацию, как [3:2] , которая вернет пустой список. В основном резка жесткая, и вам нужно будет решить, как вы хотите ее реализовать, но, надеюсь, это начало.

http://www.stackoverflow.com/questions/3911483/python-slice-how-to-i-know-the-python-slice-but-how-can-i-use-built-in-slice-ob

(Спасибо @JonClements за все предложения в чате.)

EDIT: теперь у нас есть некоторые обработчики, если у вас есть пустой список. @wim предлагает создать ошибку для одиночного доступа и возвращать [] для срезов. На самом деле это зависит от вас, что вы хотите сделать, но это показалось мне разумным, вот что я включил в этот ответ.

EDIT EDIT: если вы используете Python 2.x, я считаю, что вам также необходимо переопределить __getslice__ .

Если вы хотите расширить класс списка для обработки и настройки …

 class UnsatList(list): def __getitem__(self, index): try: return list.__getitem__(self, index % len(self)) except ZeroDivisionError: raise IndexError('list assignment index out of range') def __setitem__(self, index, value): try: return list.__setitem__(self, index % len(self), value) except ZeroDivisionError: raise IndexError('list assignment index out of range') if __name__ == '__main__': test_list = UnsatList([1,2,3,4]) assert test_list[0] == 1 assert test_list[4] == 1 assert test_list[8] == 1 assert test_list[-8] == 1 test_list[4] = 5 assert test_list[0] == 5 assert test_list[4] == 5 assert test_list[8] == 5 assert test_list[-8] == 5 

Вот решение, но помните Zen of Python : Flat лучше, чем вложенный.

Вы можете написать, например:

 a = [1, [2]] a[1].append(a) 

Тогда ваш список a имеет «бесконечную глубину», и вы можете циклически перемещаться по этим двум элементам, повторяя:

 a[0] a = a[1] 

Вы не можете этого сделать, не играя с глубиной, потому что в отличие от, например, Lisp, списки Python представляют собой массивы переменной длины, а не связанные списки.

Вот несколько функций, которые можно делать автоматически:

 def loopify(a): r = b = [] for x in a: b.append(x) b.append([]) c = b b = b[1] c[1] = r return r def loopgen(a): while True: yield a[0] a = a[1] 

Затем с вашим примером:

 musical_scale = loopify(['C', 'D', 'E', 'F', 'G', 'A', 'B']) g = loopgen(musical_scale) [next(g) for i in range(20)] 

Это дает:

['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C', 'D', 'E', 'F', 'G', ' A, B, C, D, E, F, G, A,

Конечно, можно также использовать модем или отслеживать текущий индекс и пересылать его в 0 при переполнении списка. Другие ответы показывают, как это сделать.

Также обратите внимание, что метод связанных списков не допускает случайного доступа, а только последовательный доступ (таким образом, генератор выше). Если вам нужно получить доступ к списку случайно, модульная арифметика является наиболее подходящим способом.

  • Переменные, пространство имен и классы
  • PyCharm не может найти модуль 'math'
  • Вырезание строки после x символов в пробеле в python
  • Как удалить строку из файла в python
  • Массив Python не работает
  • кодек не может кодировать символ: символьные карты в <undefined>
  • Запросы Python - управление файлами cookie
  • Как удалить последние n символов из строки?
  •  
    Interesting Posts for Van-Lav

    Как скрыть окно консоли в python?

    Переписывание цикла for в чистом NumPy для уменьшения времени выполнения

    python: самый элегантный способ пересечения списка с элементом

    Чтение из CSV: разделитель должен быть строкой, а не юникодом

    Django vs webapp2 в App Engine

    Невозможно изменить состояние проверяемого QListViewItem с помощью настраиваемого виджета

    В сценарии Python, как установить PYTHONPATH?

    Исключения для Python: EAFP и что действительно исключительное?

    Применение декораторов python к методам в классе

    Выполнение модульных тестов по вложенным функциям

    Подождите, пока не закончится определенный процесс (зная «pid»)

    Чтение нескольких номеров из текстового файла

    pySerial очень странное поведение … Код работает, когда выполняется в оболочке, но не в скрипте

    Получить все возможные совпадения для регулярных выражений (в python)?

    Устранение неполадок Websockets с EC2 на AWS с использованием Django

    Python - лучший язык программирования в мире.