Циклы в Python

Выбор правильной конструкции цикла Python предлагает множество конструкций для выполнения циклов. В этой статье они представлены и даны советы по их конкретному использованию. Кроме того, мы также рассмотрим производительность каждой конструкции цикла в вашем коде Python. Это может быть для вас неожиданностью. Циклы, циклы, циклы Язык программирования обычно состоит из нескольких типов базовых элементов, таких как присваивания, операторы и циклы. Идея цикла состоит в том, чтобы повторять отдельные действия, указанные

Выбор правильной конструкции цикла

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

Петли, петли, петли

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

  • пока заданное условие истинно (пока условие do sth.)
  • пока не будет выполнено определенное условие (выполните что-то до выполнения условия)
  • для фиксированного количества шагов (итераций) (для / от 'x' до 'y' сделать что-то.)
  • бесконечный цикл и выход / прерывание по условию (в то время как условие1 выполняет sth. и выходит по условию2)

Конструкции цикла, поддерживаемые Python

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

Базовые циклы while

 while condition: 
 statements 

До тех пор , как «условия» соблюдены все утверждения в теле в while цикла выполняются по крайней мере один раз. После каждого выполнения операторов условие повторно оценивается. Написание цикла выглядит так:

Листинг 1

 fruits = ["banana", "apple", "orange", "kiwi"] 
 position = 0 
 while position < len(fruits): 
 print(fruits[position]) 
 position = position + 1 
 print("reached end of list") 

Этот код выведет один элемент списка после следующего:

 banana 
 apple 
 orange 
 kiwi 
 reached end of list 

while Циклы с условием else

Эта конструкция специфична для языка Python, но весьма полезна:

 while condition: 
 statements 
 else: 
 statements 

Это в while цикл действует аналогично обычной в while цикла, введенные ранее. Операторы в части else выполняются, как только условие перестает выполняться. Например, если достигнут конец списка, как в нашем предыдущем примере. Вы можете интерпретировать это как then , если условие цикла больше не встречались.

Листинг 2

 fruits = ["banana", "apple", "orange", "kiwi"] 
 position = 0 
 while position < len(fruits): 
 print(fruits[position]) 
 position = position + 1 
 else: 
 print("reached end of list") 

Это выведет один элемент списка после следующего, а также дополнительный текст из print в предложении else:

 banana 
 apple 
 orange 
 kiwi 
 reached end of list 

Этот вид цикла с предложением else удобен для вывода сообщений или выполнения операторов в случае сбоя вашего условия.

Одна важная вещь , чтобы отметить , что else условие не выполняется , если break из в while цикл или если ошибка возникает внутри в while цикла.

Бесконечные циклы while

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

Вот лишь несколько вариантов использования бесконечных циклов:

  • устройства, которые пытаются поддерживать сетевые соединения активными, например точки беспроводного доступа
  • клиенты, которые пытаются постоянно обмениваться данными с хост-системой, например с сетевой файловой системой (NFS или Samba / CIFS)
  • игровые циклы для рисования и обновления состояния игры
1
<!-- -->
 while True: 
 if condition: 
 break 
 statements 

Имейте в виду, что операторы в теле бесконечного цикла выполняются хотя бы один раз. Вот почему я рекомендую писать условие прерывания как самый первый оператор после заголовка цикла. Следуя нашему примеру кода, бесконечный цикл выглядит следующим образом:

Листинг 3

 fruits = ["banana", "apple", "orange", "kiwi"] 
 position = 0 
 while True: 
 if position >= len(fruits): 
 break 
 print(fruits[position]) 
 position = position + 1 
 print("reached end of list") 

for циклов с итератором

Работа со списками описывается как использование ключевого слова for в сочетании с итератором. Псевдокод выглядит следующим образом:

 for temp_var in sequence: 
 statements 

Это упрощает код Python для обработки нашего списка следующим образом:

Листинг 4

 fruits = ["banana", "apple", "orange", "kiwi"] 
 for food in fruits: 
 print(food) 
 print("reached end of list") 

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

Если список пуст, операторы в теле цикла не выполняются. Изменение списка с точки зрения добавления или удаления элементов внутри цикла for может запутать интерпретатор Python и вызвать проблемы, поэтому будьте осторожны.

for циклов с итератором и предложением else

Аналогично в while цикл, Python также предлагает else заявление для for цикла. Он работает аналогично и может интерпретироваться как then , так же, как и раньше. Псевдокод выглядит следующим образом:

 for temp_var in sequence: 
 statements 
 else: 
 statements 

Используя это ключевое слово, наш код изменяется следующим образом:

Листинг 5

 fruits = ["banana", "apple", "orange", "kiwi"] 
 for food in fruits: 
 print(food) 
 else: 
 print("reached end of list") 

Неподдерживаемые конструкции цикла

Как было сказано в начале, существует много разных стилей петель. Однако Python не поддерживает их все. Python не поддерживает цикл do-until foreach , как, возможно, известно из PHP. Такие случаи решаются с помощью in который создает довольно привлекательный код, если вы с ним знакомы. См. Альтернативные способы написания цикла сверху.

Какую петлю выбрать?

В общем случае while condition требуют, чтобы условие было указано перед операторами цикла. Это может привести к тому, что операторы в теле цикла никогда не будут выполнены. Кроме того, не всегда ясно, сколько раз цикл будет выполняться для циклов while Вместо этого for циклы сосредотачиваются на итераторе, который указывает, как часто выполняются операторы в теле цикла.

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

Повышение качества вашего кода

Многие молодые программисты не всегда заботятся о качестве своего кода, в основном потому, что они выросли в то время, когда никто не должен думать о памяти и мощности процессора - у нас их просто много на современных компьютерах. Вместо этого более опытные (также известные как «старые») разработчики более склонны оптимизировать свой код в максимально возможной степени и могут помнить о подсчете инструкций ЦП и количества используемых ячеек памяти.

Итак, что означает качество сегодня? С точки зрения эффективности он охватывает написание минимального количества кода, насколько это возможно, и эффективное выполнение кода - только столько инструкций процессора, сколько необходимо. Во-первых, с сегодняшними интерпретаторами, средами выполнения и фреймворками довольно сложно рассчитать это должным образом, а во-вторых, это всегда компромисс между этими двумя показателями. Ключевой вопрос заключается в том, как часто этот код будет использоваться и сколько времени мы должны потратить на его оптимизацию, чтобы выиграть несколько микросекунд процессорного времени.

В качестве примера мы рассмотрим for выполняющий итерацию по списку. Обычно мы пишем это так:

Листинг 6

 for entry in range(0, 3): 
 print(entry) 

Это выводит значения 0, 1 и 2. Метод range() создает iterable [0, 1, 2] каждый раз, когда оценивается заголовок цикла. Поэтому лучше писать так:

Листинг 7

 entryRange = range(0, 3) 
 for entry in entryRange: 
 print(entry) 

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

Кроме того, эти утверждения могут быть выражены как в while цикла:

Листинг 8

 entryRange = range(0, 3) 
 index = 0 
 while index < len(entryRange): 
 print(entryRange[index]) 
 index = index + 1 

К этому моменту даже использование функции range() кажется бессмысленным. Вместо этого мы могли бы просто использовать константу для условного index и индекса в качестве счетчика для условного выражения и печати:

 index = 0 
 while index < 3: 
 print(index) 
 index = index + 1 

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

Тесты производительности

До сих пор мы говорили о коде цикла и о том, как его правильно написать. Тест производительности может помочь пролить свет. Идея любезно позаимствована из интересной статьи в блоге Неда Батчелдера [1].

Используется perf , который выполняет тесты производительности для исполняемого программного кода [2]. Базовый вызов - это perf stat program тогда как stat сокращает статистику, а программа - это вызов, который мы хотели бы оценить. Для тестирования наших вариантов цикла были сделаны следующие вызовы:

Листинг 9

 perf stat python3 while-1.py 
 perf stat python3 while-2.py 
 perf stat python3 while-3.py 
 perf stat python3 for-4.py 
 perf stat python3 for-5.py 
 perf stat python3 for-6.py 
 perf stat python3 for-7.py 
 perf stat python3 while-8.py 

Это среднее значение для 10 запусков из-за разницы в загрузке ядра Linux. В следующей таблице показаны результаты:

Тема Листинг 1 Листинг 2 Листинг 3 Листинг 4 Листинг 5


часы задачи (мсек) 20.160077 18,535264 15,975387 15.427334 15.503672 переключатели контекста 10 11 10 13 10 миграции ЦП 0 0 2 1 1 ошибки страницы 851 849 855 848 851 циклы 41 915 010 44 938 837 44 403 696 42 983 392 42 489 206 инструкции 46 833 820 46 803 187 46 926 383 46 596 667 46 701 350

Для листингов 6-8 это выглядит следующим образом:

Тема Листинг 6 Листинг 7 Листинг 8


часы задачи (мсек) 16,480322 18.193437 15.734627 переключатели контекста 9 11 11 миграции ЦП 0 0 1 ошибки страницы 850 851 853 циклы 42 424 639 42 569 550 43 038 837 инструкции 46 703 893 46 724 190 46 695 710

Заключение

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

Ссылки и ссылки

Благодарности

Автор благодарит Герольда Рупрехта и Мэнди Ноймайер за их поддержку и комментарии при подготовке этой статьи.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus