Рубрики
Без рубрики

Мертвый простой Python: Итерационные электроинструменты

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

Мертвый простой Python (13 частей серии)

Предыдущий раздел более или менее закончился на Cliffhanger.

Когда мы в последний раз покинули наш герой, Мы обнаружили петли и итераторы в Python и почувствовали немного потенциала, которую они предлагают.

У меня есть несколько слов выбора из моих редакторов: «Вы покинули ZIP () и перечислять () и это, безусловно, Очень Важно для любого обсуждения итераторов! ” Да, они, но статья получила немного долго. Никогда не бойтесь, хотя – мы собираемся решать их и многое другое!

Кстати, если вы еще не прочитали предыдущий раздел, «петли и итераторы», вы захотите вернуться и сделать это сейчас! Не волнуйся, я подожду.

Может показаться странным посвятить всю статью в нескольких встроенных функциях, но они способствуют много магии в Python.

Помните Диапазон () Функция из предыдущей статьи? Мы кратко охватываем, как его можно использовать для генерации последовательности чисел, но она имеет больше энергии, чем кажется, на первый взгляд.

Начать и остановиться

Первое препятствие для использования Диапазон () понимает аргументы: Диапазон (запуск, остановка) Отказ Начать это включительно ; Мы начинаем на этот фактический номер. Стоп Однако, однако, это эксклюзивный , означает, что мы останавливаемся, прежде чем мы доберемся туда!

Итак, если у нас есть Диапазон (1, 10) мы получаем [1, 2, 3, 4, 5, 6, 7, 8, 9] . Начнем на 1 , но мы никогда не добирались до 10 ; Мы остановимся в одной короткой.

Если бы мы хотели включить 10 В нашей последовательности нам нужно Диапазон (1, 11) : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Отказ

Кстати, если мы уточним только один аргумент, как Диапазон (10) Предположим, что начало диапазона является 0 Отказ В этом случае мы получили [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] . Вы увидите Диапазон () Используется таким образом, когда он используется для контроля традиционного для цикла.

Пропуская

Мой любимый трюк с Диапазон () это опционально Третий Аргумент: Когда вы указываете Диапазон (запуск, остановка, шаг) , шаг Аргумент позволяет увеличить значения Большой чем 1 Отказ

Одним из употреблений можно распечатать все кратки 7, из 7 Сам 700 , включительно: Диапазон (7, 701, 7) сделал бы только это. (Примите заметку, я указал 701 Для окончания, чтобы убедиться, что 700 бы ?| быть включен.)

Другое использование может быть распечатать все нечетные номера менее 100: Диапазон (1, 100, 2) Отказ

Хранирование диапазонов

Если вы пытаетесь выбрать, вы, вероятно, заметите, что это не делает то, что вы ожидаете:

sevens = range(7, 701, 7)
print(sevens)

Команда печати печатает буквальную фразу Диапазон (7, 701, 7) Отказ Это не то, что мы хотели!

Помните, Диапазон () Возвращает объект, который является Как итератор (но не совсем). Чтобы сохранить это как список прямо, нам нужно явно повернуть его в Список, упаковывая его в Список () Функция:

sevens = list(range(7, 701, 7))
print(sevens)

Сейчас что Выход – это то, что мы хотели – список первых сотен кратных 7!

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

Говоря о списках, давайте поставить один вместе:

dossiers = ['Sir Vile', 'Dr. Belljar', 'Baron Grinnit', 'Medeva', 'General Mayhem', 'Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']

Следуете ли вы это или нет, вы уже знаете нормальный индексную запись.

print(dossiers[1])
>>> Dr. Belljar

Что вернуло второй элемент (индекс 1 ) досье контейнер. Достаточно просто, верно? Практически все языки предлагают это поведение.

Итак, что, если мы хотим второй и третий элементы?

print(dossiers[1:3])
>>> ['Dr. Belljar', 'Baron Grinnit']

Что сейчас произошло? В расширенном обозначении индексации у нас есть три аргумента, разделенные двоеточиями: Начать , Стоп и шаг . Эй, звучит знакомо? Это должны – это те же аргументы, которые Диапазон () использует! Они тоже работают так же. (Конечно, мы остановились на третий аргумент [ Step ] в примере выше.)

Обратите внимание, что пример печатается Доктор Белледжар (индекс 1 ) и Барон Гриннит (индекс 2 ), но не Медева С Потому что Стоп аргумент исключительно; Мы останавливаемся просто о ней.

Обратите внимание, Начать Должно быть меньше чем Стоп Для вас, чтобы получить какие-либо результаты! Есть исключение, хотя, что мы поговорим в ближайшее время.

Теперь, что если вы хотите каждый другой Досье, начиная со второго?

print(dossiers[1::2])
>>> ['Dr. Belljar', 'Medeva', 'Buggs Zapper', 'Jane Reaction']

Вы заметите, что мы не уточняли Стоп Отказ Нам на самом деле не нужно! Расширенная уведомление индексации позволяет вам оставлять любые аргументы, пока у вас есть двоеточие, чтобы разделить все. Поскольку второй аргумент был опущен, мы просто поставили дополнительные : после того, как это было бы.

Идти назад

Расширенная индексация требует обозначения (запуск, остановка, шаг) Логика еще один шаг дальше, позволяя вам работать назад! Сначала это немного мозга Twister, хотя, так что держитесь на туго …

print(dossiers[-1])

Который печатает Последний пункт в списке. Отрицательные номера начинают подсчитывать с конца списка! Это может чувствовать себя немного странно, так как мы привыкли подсчитать от 0 В индексах, но отрицательный ноль на самом деле не вещь, поэтому мы начинаем с -1 .

Учитывая, как мы печатаем последние три предмета? Мы могли бы попробовать это, но это на самом деле не будет работать ….

print(dossiers[-1:-4])
>>> []

Это возвращает пустой список. Почему? Помните, Начать Должно быть меньше чем Стоп даже при работе с негативными показателями. Итак, мы должны поставить -4 Как наше Начать С -4 <-1 Отказ

print(dossiers[-4:-1])
>>> ['Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction']

Это ближе, но есть еще проблема. Диакпарция Ди Это наш последний пункт, так где же она? Помните, Стоп исключительно; Мы останавливаемся просто застенчивым. Но мы не можем просто сказать досье [-4] , так как это только даст нам Buggs Zapper . И досье [-4: -0] не действителен.

Способ решения этого – сказать Python, мы явно пропускаем второй аргумент: Положите толстой кишки после нашего первого аргумента Действительно

print(dossiers[-4:])
>>> ['Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']

Отлично, теперь мы видим до конца, кроме сейчас у нас слишком много информации. Мы хотим последнее Три , так что давайте изменим -4 к -3

print(dossiers[-3:])
>>> ['Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']

Тар, она дует!

Говоря о магии, что вы думаете, произойдет, если мы поместим отрицательное число в третьем аргументе, шаг ? Давай попробуем -1 С двумя дюгониями, предшествующими его, чтобы указать, что мы хотим весь список.

print(dossiers[::-1])
>>> ['Dee Cryption', 'Jane Reaction', 'Jacqueline Hyde', 'Buggs Zapper', 'General Mayhem', 'Medeva', 'Baron Grinnit', 'Dr. Belljar', 'Sir Vile']

Эй, это отпечатывает все назад! Действительно, а шаг -1 Переверняет список.

Теперь давайте попробуем -2

print(dossiers[::-2])
>>> ['Dee Cryption', 'Jacqueline Hyde', 'General Mayhem', 'Baron Grinnit', 'Sir Vile']

Разве это не только это обратный список, но он пропустил каждый другой элемент. Отрицательный шаг ведет себя точно так же, как положительный шаг За исключением того, что это работает назад!

Итак, что если мы хотели собрать все вместе? Возможно, мы хотим перечислить второй, третий и четвертый элементы в обратном порядке …

print(dossiers[2:5:-1])
>>> []

Gotcha Alert: Начать и Стоп должен быть в порядке прохождения. Если шаг положительный, Начать должно быть меньше, чем Стоп ; Однако, если шаг негативно, Начать должен быть больше, чем остановка !

Вы можете подумать об этом, как ходьба для фоторегулярия. шаг говорит вам, какой путь ходить и насколько велик должен быть ваш шаг. Вы начинаете фотографировать, как только вы доберетесь до Начать и как только вы столкнетесь остановка Вы поставили камеру.

Итак, чтобы исправить это, нам нужно поменять нашему Начать и Стоп Отказ

print(dossiers[5:2:-1])
>>> ['Buggs Zapper', 'General Mayhem', 'Medeva']

Сторона Примечание: Python также предоставляет ломтик () и Itertools.islice () Функции, которые ведут себя так же одинаково. Однако они оба более ограничены, чем расширенная нотация индексации, поэтому вы почти всегда лучше используете это вместо функций.

Остальные функции мы будем изучать в этом разделе работать с Iterables Отказ Пока я буду использовать списки для большинства примеров, помните, что вы можете использовать любой с этим, включая Диапазон () функция.

все и любое

Представьте себе, что вы получили целую кучу данных, такие как список сотен имен, в неразъемлемом контейнере, например, в списке. Прежде чем кормить этот список в свой Super Brilliant Algorith, вы хотите сохранить некоторое время обработки, проверяя, что у вас на самом деле есть строковое значение в каждый элемент , без исключений.

Это то, что все Функция для.

dossiers = ['Sir Vile', 'Dr. Belljar', 'Baron Grinnit', 'Medeva', 'General Mayhem', 'Buggs Zapper', '', 'Jane Reaction', 'Dee Cryption']
print(all(dossiers))
>>> False

Вы можете вспомнить, пустую строку ( '' ) оценивает Ложь в питоне. все () Функция оценивает каждый элемент и обеспечивает возврат Правда Отказ Если даже один оценивает Ложь , все () Функция также вернет ложь.

любой () Работает почти таким же образом, за исключением того, что он требует только одного элемента для оценки Правда Отказ

Это не может показаться ужасно полезным на первом руме, но в сочетании с некоторыми другими инструментами или даже состязаниями списка (позже раздел) они могут сэкономить много времени!

перечислять

В цикле, если вам нужно получить доступ как на ценности списка и их Индексы , вы можете сделать это с перечислять () функция.

foo = ['A', 'B', 'C', 'D', 'E']

for index, value in enumerate(foo):
    print(f'Element {index} is has the value {value}.')

перечислять () Однако не ограничивается списками. Как и все эти другие функции, это работает на любой Указательны, нумерация (или перечисление) каждая из значений возвращается. Например, мы можем использовать его на Диапазон () Отказ Давайте использовать его для распечатки каждого распечатки от 10 с 10 до 100 ( Диапазон (10,101,10) ). Мы перечисляем это …

for index, value in enumerate(range(10,101,10)):
    print(f'Element {index} is has the value {value}.') 

Это дает нам …

Element 0 is has the value 10.
Element 1 is has the value 20.
Element 2 is has the value 30.
Element 3 is has the value 40.
Element 4 is has the value 50.
Element 5 is has the value 60.
Element 6 is has the value 70.
Element 7 is has the value 80.
Element 8 is has the value 90.
Element 9 is has the value 100

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

for index, value in enumerate(range(10,101,10), 1):
    print(f'{index} times 10 equals {value}')

Когда мы бежим этим, мы получаем …

1 times 10 equals 10
2 times 10 equals 20
3 times 10 equals 30
4 times 10 equals 40
5 times 10 equals 50
6 times 10 equals 60
7 times 10 equals 70
8 times 10 equals 80
9 times 10 equals 90
10 times 10 equals 100

фильтр

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

locations = {
    'Parade Ground': 0,
    'Ste.-Catherine Street': 0,
    'Pont Victoria': 0,
    'Underground City': 3,
    'Mont Royal Park': 0,
    'Fine Arts Museum': 0,
    'Humor Hall of Fame': 2,
    'Lachine Canal': 4,
    'Montreal Jazz Festival': 1,
    'Olympic Stadium': 0,
    'St. Lawrence River': 2,
    'Old Montréal': 0,
    'McGill University': 0,
    'Chalet Lookout': 0,
    'Île Notre-Dame': 0
    }

Возможно, нам нужно найти все места, которые имеют подсказки и игнорируют остальные. Начнем с написания функции для проверки конкретной кортежной пары ключа. Это может показаться нелепой недостаточностью, но на мгновение это имеет смысл:

def has_clues(pair):
    return bool(pair[1])

Мы будем отправлять каждую пару из словаря к функции в качестве кортежа, поэтому пара [1] будет стоимость (Е.Г. («Подземный город», 3) ). Встроенная функция Bool () вернется Ложь Если номер является 0 , а также Правда Для всего остального, что именно то, что мы хотим.

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

for place, clues in filter(has_clues, locations.items()):
    print(place)

Примите к работе, мы не включаем скобки после has_clues. . Мы передаем фактическую функцию как объект Действительно Фильтр сделаю фактическое призвание.

Конечно, работает, запустил этот код отпечатывает пять мест, где у нас были подсказки (значения> 0 ) …

Underground City
Humor Hall of Fame
Lachine Canal
Montreal Jazz Festival
St. Lawrence River

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

for place, clues in filter(lambda x:bool(x[1]), locations.items()):
    print(place)

карта

карта () функционирует аналогично Фильтр () За исключением, за исключением вместо этого функции для опускания элементов из итеративного, она используется для Изменить их.

Давайте представим, что у нас есть список температур в Фаренгейте:

temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]

Мы хотим преобразовать их все в Целью, поэтому мы пишем функцию для этого.

def f_to_c(temp):
    return round((temp - 32) / 1.8, 1)

Мы можем использовать карта () Функция, чтобы применить это к каждому значению в Temps Производя итератор, мы можем использовать в петле (или где угодно).

for c in map(f_to_c, temps):
    print(f'{c}°C')

Помните, мы проезжаем Функциональный объект f_to_c. Как первый аргумент карта () Итак, мы оставляем скобки!

Бег этот цикл дает нам:

19.4°C
22.5°C
21.8°C
25.8°C
16.7°C
27.0°C

мин и макс

Давайте продолжим работать с этими температурами на мгновение. Если бы мы хотели найти самый низкий или самый высокий В списке мы могли бы использовать мин () или Макс () Функции соответственно. Не много для этого, правда.

temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]
print(min(temps))
>>> 62.1
print(max(temps))
>>> 80.6

Сторона Примечание: Не связанные с ейтенами, вы также можете использовать эти функции, чтобы найти наименьшего или крупнейшего из списка аргументов, которые вы его даете, например Мин (4, 5, 6, 7, 8) , что бы вернулось 4 Отказ

сортируется

Часто вы захотите сортировать утечку. Python делает это очень эффективно через отсортировано () Встроенная функция.

temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]
for t in sorted(temps):
    print(t)

Это производит …

62.1
67.0
71.3
72.5
78.4
80.6

перевернутый

Большую часть времени, расширенная индексация обозначения [:: - 1] позволит вам поменять список или другие заказанные порядок. Но если это не вариант, вы также можете использовать перевернуты () функция.

Например, я сочеб в сочетании с отсортировано () Функция с минуты назад …

temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]
for t in reversed(sorted(temps)):
    print(t)

Это дает нам …

80.6
78.4
72.5
71.3
67.0
62.1

сумма

Еще одна быстрая встроенная функция – сумма () , который добавляет все элементы в съемке вместе. Естественно, это только работает, если все элементы может быть добавленным вместе.

Одно использование этого было бы в нахождении среднего количества этих температур раньше. Вы можете вспомнить, что Лен () Функция говорит нам, сколько элементов в контейнере.

temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]
average = sum(temps) / len(temps)
print(round(average, 2))
>>> 71.98 

zip.

Помните, что более ранний пример о местонахождениях и подсказках? Представьте, что мы получили эту информацию, а не в словаре, но в двух списках:

locations = ['Parade Ground', 'Ste.-Catherine Street', 'Pont Victoria', 'Underground City', 'Mont Royal Park', 'Fine Arts Museum', 'Humor Hall of Fame', 'Lachine Canal', 'Montreal Jazz Festival', 'Olympic Stadium', 'St. Lawrence River', 'Old Montréal', 'McGill University', 'Chalet Lookout', 'Île Notre-Dame']
clues = [0, 0, 0, 3, 0, 0, 2, 4, 1, 0, 2, 0, 0, 0, 0]

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

К счастью, zip () Функция может помочь нам иметь смысл этих данных по Агрегация Это на кортежи, используя итератор, давая нам (Расположение [0], подсказки [0]), (местоположения [1], подсказки [1]), (местоположения [2], подсказки [2]) и так далее.

zip () Функция даже не ограничена двумя поемами; Он может настроить Zip вместе, сколько мы даем! Если нет, у всех нет той же длины, любые «дополнения» будут тусоваться в конце.

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

data = list(zip(locations, clues))
print(data)

Это дает нам структуру, не в отличие от того, что мы получили из словаря .items () Функция ранее!

[('Parade Ground', 0), ('Ste.-Catherine Street', 0), ('Pont Victoria', 0), ('Underground City', 3), ('Mont Royal Park', 0), ('Fine Arts Museum', 0), ('Humor Hall of Fame', 2), ('Lachine Canal', 4), ('Montreal Jazz Festival', 1), ('Olympic Stadium', 0), ('St. Lawrence River', 2), ('Old Montréal', 0), ('McGill University', 0), ('Chalet Lookout', 0), ('Île Notre-Dame', 0)]

На самом деле, если я вспомню мой Фильтр () Функция с лямбда, я могу настроить его для использования Zip , позволяя нам работать чисто из двух списков:

for place, clues in filter(lambda x:bool(x[1]), zip(locations, clues)):
    print(place)

Как и прежде, это выводы …

Underground City
Humor Hall of Fame
Lachine Canal
Montreal Jazz Festival
St. Lawrence River

Я покрыл практически все встроенные функции Python для работы с повторными, но в Itertools модуль. Я настоятельно рекомендую Чтение документации Узнать больше.

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

Если вы все еще ждетете тех, которые давно обещанные генераторы и список поступлений, никогда не бойтесь! Они придумывают в самых следующих разделах.

Как всегда, я рекомендую вам прочитать документацию:

Мертвый простой Python (13 частей серии)

Оригинал: “https://dev.to/codemouse92/dead-simple-python-iteration-power-tools-3i3n”