English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
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(['北京', '上海', '广州', '深圳']): print(x)
実行結果は以下の通りです:
C:\Python\Python35\python.exe E:/python-intensive-training/s2.py 北京:低温 21℃ 、高温 30℃ 上海:低温 23℃ 、高温 26℃ 广州:低温 26℃ 、高温 34℃ 深圳:低温 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__メソッドを実行生成器関数として実装し、毎回yieldで素数を返します
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 プロセスが終了しました。終了コード 0
三、どのように逆方向のイテレーションを行うかおよびどのように実装するか?
実際のケース
連続浮動小数生成器FloatRange(をrrangeに似せて)を実装し、指定された範囲(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
4、イテレータに対してスライス操作を行う方法はどうですか?
実際のケース
あるテキストファイルがあり、その中の特定の範囲の内容を取得したい場合、例えば100~300行までの内容、Pythonのテキストファイルはイテレーション可能なオブジェクトであり、リストのスライスのように似た方法でスライスを使用して取得できますか?100~300行のファイル内容の生成器を取得できますか?
解決策
標準ライブラリのitertools.isliceを使用すると、迭代器オブジェクトのスライスの生成器を返すことができます。
from itertools import islice f = open('access.log') # # 前500行 # islice(f, 500) # # 100行以降の # islice(f, 100, None) for line in islice(f,100,300): print(line)
isliceは前のイテレーションオブジェクトを消費します。
l = range(20) t = iter(l) for x in islice(t, 5, 10): print(x) print('2回目のイテレーション') for x in t: print(x)
出力結果
C:\Python\Python35\python.exe E:/python-intensive-training/s5.py 5 6 7 8 9 2回目のイテレーション 10 11 12 13 14 15 16 17 18 19 プロセスが終了しました。終了コード 0
5、for文で複数のイテレーション可能なオブジェクトをどのようにイテレートしますか?
実際のケース
1あるクラスの生徒の期末試験の成績、国語、数学、英語がそれぞれ保存されています。3リストを順次イテレートしながら、各学生の合計点(並列)を計算します。
2ある学年には4つのクラスがあり、その回の試験の各クラスの英語の成績が4つのリストにそれぞれ保存されています。各リストを順次イテレートし、全学年の成績が高い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
まとめ
これがこの記事の全ての内容です。皆様の学習や仕事に少しでも役立つことを願っています。何かご不明な点があれば、コメントを残してください。