Если мы рассмотрим общие сценарии, в которых может быть выбрано это исключение, доступ к свойствам с объектом вверху.
Пример:
string postalcode=Customer.Address.PostalCode;
//if customer or address is null , this will through exeption
здесь, если адрес равен нулю, то вы получите NullReferenceException.
Итак, в качестве практики мы всегда должны использовать проверку нуля, прежде чем обращаться к свойствам в таких объектах (особенно в общих)
string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception
Я обсуждал это некоторое время, потому что подобные вопросы задавались много раз здесь. Но это просто уникально, чтобы получить преимущество от сомнений. (Тем не менее, я не буду возражать, если другие голосуют, чтобы закрыть.) Вот визуальное объяснение того, что происходит.
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 0; remove? no
^
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 1; remove? yes
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 3; remove? no
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 4; remove? yes
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 6; remove? no
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 7; remove? yes
^
[0, 2, 3, 5, 6, 8, 9] <- b = 9; remove? no
^
Поскольку никто больше не имеет, я попытаюсь ответить на ваши другие вопросы:
Почему не указана ошибка, указывающая, что базовый итератор изменяется?
blockquote>Чтобы выбросить ошибку, не запрещая многие совершенно правильные конструкции контуров, Python должен был знать lot о том, что происходит, и, вероятно, это должно было бы получить информацию во время выполнения. Вся эта информация потребует времени для обработки. Это сделало бы Python намного медленнее, только в том месте, где скорость действительно рассчитывается - цикл.
Изменились ли механики из более ранних версий Python в отношении этого поведения?
blockquote>Короче говоря, нет. Или, по крайней мере, я сильно сомневаюсь в этом, и, конечно, он вел себя так, так как я узнал Python (2.4). Честно говоря, я бы ожидал, что любая простая реализация изменчивой последовательности будет вести себя именно таким образом. Любой, кто знает лучше, пожалуйста, поправьте меня. (На самом деле быстрый поиск документов подтверждает, что текст, указанный Mikola , приведен в учебнике с версии версии 1.4 !) [/ G9]
На вашей первой итерации вы не удаляетесь и все денди.
Вторая итерация вы находитесь в позиции [1] последовательности, и вы удаляете «1». Итератор затем перенесет вас в позицию [2] в последовательности, которая теперь «3», поэтому «2» пропускается (поскольку «2» теперь находится в позиции [1] из-за удаления). Конечно, «3» не удаляется, поэтому вы переходите к позиции [3] в последовательности, которая теперь «4». Это удаляется, вы попадаете на позицию [5], которая теперь «6» и т. Д.
Тот факт, что вы удаляете вещи, означает, что позиция пропускается каждый раз, когда вы выполняете удаление .
Конечно, небезопасно изменять массив, когда вы выполняете итерацию по нему. Спектр говорит, что это плохая идея, и поведение не определено:
http://docs.python.org/tutorial/controlflow.html#for-statements
Итак, следующий вопрос: что именно происходит здесь под капотом? Если бы я должен был догадаться, я бы сказал, что он делает что-то вроде этого:
for(int i=0; i<len(array); ++i)
{
do_loop_body(i);
}
Если вы полагаете, что это действительно то, что происходит, то это полностью объясняет наблюдаемое поведение. Когда вы удаляете элемент на или до текущего указателя, вы перемещаете весь список на 1 влево. В первый раз вы удаляете 1 - как обычно - но теперь список сдвигается назад. Следующая итерация вместо удара 2, вы нажмете 3. Затем вы удалите 4, и список сдвинется назад. Следующая итерация 7 и т. Д.
Как объяснил Микола, фактический результат, который вы наблюдаете, вызван тем фактом, что удаление записи из списка смещает весь список на одно место, заставляя вас пропускать элементы.
Но более интересный вопрос , на мой взгляд, почему python не выбирает для создания сообщения об ошибке, когда это происходит. Он вызывает такое сообщение об ошибке, если вы попытаетесь изменить словарь. Я думаю, для этого есть две причины.