English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Техники итерации и的反迭代 в Python

1. Как реализовать объект итерируемого объекта и объект итератора?

Реальный случай

Некоторое программное обеспечение требует извлечения информации о запахах городов из Интернета и их последующего отображения:

Пекин: 15 ~ 20 Тяньцзинь: 17 ~ 22 Чанчунь: 12 ~ 18 ......

Если сразу抓取所有城市天气并显示,则在显示第一个城市气温时会有很高的延迟,并且会浪费存储空间,мы хотим использовать стратегию доступа по времени и封装所有城市气温 в один объект, который можно итерировать с помощью оператора for, как решить эту проблему?

Решение

Реализовать объект итератора Weatherlterator, метод next возвращает температуру города, реализовать объект итерируемого объекта Weatherlterable, метод iter__ возвращает объект итератора

import requests from collections import Iterable, Iterator # Параметр погоды итератор class WeatherIterator(Iterator): def __init__(self, cities): self.cities = cities self.index = 0 def getWeather(self, city): r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=' + city) data = r.json()['data']['forecast'][0] return '%s:%s , %s' % (city, data['low'], data['high']) def __next__(self): if self.index == len(self.cities): raise StopIteration city = self.cities[self.index] self.index += 1 return self.getWeather(city) # Объект итерируемый class WeatherIterable(Iterable): def __init__(self, cities): self.cities = cities def __iter__(self): return WeatherIterator(self.cities) for x in WeatherIterable(['Пекин', 'Шанхай', 'Гуанчжоу', 'Шenzhen']): print(x)

Результат выполнения:

C:\Python\Python35\python.exe E:/python-intensive-training/s2.py Пекин: низкая температура 21℃ , высокая температура 30℃ Шанхай: низкая температура 23℃ , высокая температура 26℃ Гуанчжоу: низкая температура 26℃ , высокая температура 34℃ Шenzhen: низкая температура 27℃ , высокая температура 33℃ Процесс завершен с кодом выхода 0

Как использовать генераторную функцию для реализации итерируемого объекта?

Реальный случай

Реализуйте класс, который является итерируемым объектом и может итерировать все простые числа в заданном диапазоне:

python pn = PrimeNumbers(1, 30) for k in pn: print(k) `` Вывод результатов text
2 3 5 7 11 13 17 19 23 29
“`

Решение

-Реализуйте метод __iter__ класса в виде генераторной функции, которая возвращает один из простых чисел

class PrimeNumbers: def __init__(self, start, stop): self.start = start self.stop = stop def isPrimeNum(self, k): if k < 2: return False for i in range(2, k): if k % i == 0: return False return True def __iter__(self): for k in range(self.start, self.stop + 1): if self.isPrimeNum(k): yield k for x in PrimeNumbers(1, 20): print(x)

Результат выполнения

C:\Python\Python35\python.exe E:/python-intensive-training/s3.py 2 3 5 7 11 13 17 19 Process finished with exit code 0

Как провести обратное итерирование и как реализовать обратное итерирование?

Реальный случай

Реализация генератора последовательных плавающих точек FloatRange (аналог rrange), который generates последовательность непрерывных плавающих точек в заданном диапазоне (start, stop) и шаге (step), например, итерация FloatRange(3.0, 4.0, 0.2) может генерировать последовательность:

Прямо: 3.0 > 3.2 > 3.4 > 3.6 > 3.8 > 4.0 Обратно: 4.0 > 3.8 > 3.6 > 3.4 > 3.2 > 3.0

Решение

Реализация протокола обратного итерирования метода __reversed__, который возвращает обратный итератор

class FloatRange: def __init__(self, start, stop, step=0.1): self.start = start self.stop = stop self.step = step def __iter__(self): t = self.start while t <= self.stop: yield t t += self.step def __reversed__(self): t = self.stop while t >= self.start: yield t t -= self.step print("Прямой итерации-----") for n in FloatRange(1.0, 4.0, 0.5): print(n) print("Обратный итерации-----") for x in reversed(FloatRange(1.0, 4.0, 0.5)): print(x)

Результаты вывода

C:\Python\Python35\python.exe E:/python-intensive-training/s4.py Прямая итерация----- 1.0 1.5 2.0 2.5 3.0 3.5 4.0 Обратная итерация----- 4.0 3.5 3.0 2.5 2.0 1.5 1.0 Процесс завершен с кодом выхода 0

Как выполнить срез операции над итератором?

Реальный случай

У нас есть某个 текстовый файл, и мы хотим получить содержимое определенного диапазона, например, содержимое строк с 100 по 300. Python текстовые файлы являются итерируемыми объектами, можем ли мы использовать способ аналогичный списковой разрезке, чтобы получить генератор содержимого файла с 100 по 300 строк?

Решение

Использование islice из стандартной библиотеки itertools возвращает генератор для срезов объекта итератора

from itertools import islice f = open('access.log') # # первые 500 строк # islice(f, 500) # # после 100 строк # islice(f, 100, None) для строки в islice(f, 100, 300): print(строка)

islice всегда потребляет предыдущий объект итерации

l = range(20) t = iter(l) для x в islice(t, 5, 10): print(x) print('Вторая итерация') для x в t: print(x)

Результаты вывода

C:\Python\Python35\python.exe E:/python-intensive-training/s5.py 5 6 7 8 9 Второй итерации 10 11 12 13 14 15 16 17 18 19 Процесс завершен с кодом выхода 0

Как итерировать несколько итерируемых объектов в одном для-операторе?

Реальный случай

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

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

Решение

Параллельность: использование内置енной функции zip, которая может объединять несколько итерируемых объектов, возвращая при каждом итерировании один тупль

from random import randint # Школьные оценки по китайскому языку, # 40 человек, оценки от 60 до 100 chinese = [randint(60, 100) for _ in range(40)] math = [randint(60, 100) for _ in range(40)] # Математика english = [randint(60, 100) for _ in range(40)] # Английский total = [] for c, m, e in zip(chinese, math, english): total.append(c + m + e) print(total)

Результат выполнения:

C:\Python\Python35\python.exe E:/python-intensive-training/s6.py [232, 234, 259, 248, 241, 236, 245, 253, 275, 238, 240, 239, 283, 256, 232, 224, 201, 255, 206, 239, 254, 216, 287, 268, 235, 223, 289, 221, 266, 222, 231, 240, 226, 235, 255, 232, 235, 250, 241, 225] Процесс завершен с кодом выхода 0

Параллельный: Использование стандартной библиотеки itertools.chain, которая может соединять несколько итерируемых объектов

from random import randint from itertools import chain # Создание случайных оценок для четырех классов e1 = [randint(60, 100) for _ in range(40)] e2 = [randint(60, 100) for _ in range(42)] e3 = [randint(60, 100) for _ in range(45)] e4 = [randint(60, 100) for _ in range(50)] # По умолчанию количество = 1 count = 0 for s in chain(e1, e2, e3, e4): # Если текущая оценка больше 90, то count + 1 if s > 90: count += 1 print(count)

Результаты вывода

C:\Python\Python35\python.exe E:/python-intensive-training/s6.py 48 Процесс завершен с кодом выхода 0

Резюме

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

Дополнительные рекомендации