NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:@"firstRun"]) {
[defaults setObject:[NSDate date] forKey:@"firstRun"];
[self displayTutorial];
}
Если вы посмотрите на 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().
Специальные методы, такие как __ 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.
Поддержка итерацией __ getitem __
может рассматриваться как «устаревшая функция», которая позволила более плавный переход, когда в PEP234 в качестве основной концепции была введена итеративность. Это применимо только к классам без __ iter __
, чей __ getitem __
принимает целые числа 0, 1 и c, и вызывает IndexError
, когда индекс становится слишком высоким (если вообще), обычно «последовательные» классы, закодированные до появления __ iter __
(хотя ничто не мешает вам кодировать новые классы таким же образом).
Лично я бы предпочел не полагаться на это в новом коде, хотя он не устарел и не является он уходит (отлично работает и в Python 3), так что это всего лишь вопрос стиля и вкуса («явное лучше, чем неявное», поэтому я
__ getitem __
предшествует протоколу итератора, и в прошлом единственный способ сделать вещи повторяемыми. Таким образом, он по-прежнему поддерживается как метод итерации. По сути, протокол для итерации следующий:
Проверить метод __ iter __
. Если он существует, используйте новый протокол итераций.
В противном случае попробуйте вызвать __ getitem __
с последовательно большими целыми значениями, пока он не вызовет IndexError.
(2) раньше был единственным способом сделать это, но имел недостаток, заключающийся в том, что предполагалось больше, чем было необходимо для поддержки простой итерации. Чтобы поддерживать итерацию, вам нужно было поддерживать произвольный доступ, что было намного дороже для таких вещей, как файлы или сетевые потоки, где переход был легким, но для возврата назад потребовалось бы все сохранить.
Это так по историческим причинам. До Python 2.2 __getitem__ был единственным способом создать класс, который можно было бы повторять с помощью цикла for. В 2.2 был добавлен протокол __iter__, но для сохранения обратной совместимости __getitem__ по-прежнему работает в циклах for.
Поскольку cb [0]
совпадает с cb .__ getitem __ (0)
. См. документацию Python по этому поводу.