Почему делает определение __ getitem __ на классе, делают это повторяемым в Python?

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:@"firstRun"]) {
    [defaults setObject:[NSDate date] forKey:@"firstRun"];
    [self displayTutorial];
}
57
задан grieve 29 May 2009 в 15:22
поделиться

6 ответов

Если вы посмотрите на PEP234 , определяющий итераторы, он говорит:

1. An object can be iterated over with "for" if it implements
   __iter__() or __getitem__().

2. An object can function as an iterator if it implements next().
47
ответ дан 24 November 2019 в 19:23
поделиться

Специальные методы, такие как __ getitem __ , добавляют объекты особого поведения, включая итерацию.

http://docs.python.org/reference/datamodel.html#object. getitem

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

Поднимите IndexError, чтобы сигнализировать об окончании последовательности.

Ваш код в основном эквивалентен:

i = 0
while True:
    try:
        yield object[i]
        i += 1
    except IndexError:
        break

Где объект - это то, что вы повторяете в цикле for.

6
ответ дан 24 November 2019 в 19:23
поделиться

Поддержка итерацией __ getitem __ может рассматриваться как «устаревшая функция», которая позволила более плавный переход, когда в PEP234 в качестве основной концепции была введена итеративность. Это применимо только к классам без __ iter __ , чей __ getitem __ принимает целые числа 0, 1 и c, и вызывает IndexError , когда индекс становится слишком высоким (если вообще), обычно «последовательные» классы, закодированные до появления __ iter __ (хотя ничто не мешает вам кодировать новые классы таким же образом).

Лично я бы предпочел не полагаться на это в новом коде, хотя он не устарел и не является он уходит (отлично работает и в Python 3), так что это всего лишь вопрос стиля и вкуса («явное лучше, чем неявное», поэтому я

61
ответ дан 24 November 2019 в 19:23
поделиться

__ getitem __ предшествует протоколу итератора, и в прошлом единственный способ сделать вещи повторяемыми. Таким образом, он по-прежнему поддерживается как метод итерации. По сути, протокол для итерации следующий:

  1. Проверить метод __ iter __ . Если он существует, используйте новый протокол итераций.

  2. В противном случае попробуйте вызвать __ getitem __ с последовательно большими целыми значениями, пока он не вызовет IndexError.

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

26
ответ дан 24 November 2019 в 19:23
поделиться

Это так по историческим причинам. До Python 2.2 __getitem__ был единственным способом создать класс, который можно было бы повторять с помощью цикла for. В 2.2 был добавлен протокол __iter__, но для сохранения обратной совместимости __getitem__ по-прежнему работает в циклах for.

5
ответ дан 24 November 2019 в 19:23
поделиться

Поскольку cb [0] совпадает с cb .__ getitem __ (0) . См. документацию Python по этому поводу.

2
ответ дан 24 November 2019 в 19:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: