Python itertools.count()の使い方|無限の連番を作る方法と止め方・range・enumerateとの違い
Pythonのitertools.count(start=0, step=1)は、startからstepずつ増える数を終わりなく返すイテレータです。count(1)なら1, 2, 3…と続くので、islice()・break・zip()のどれかで必ず止めて使います。range()と違って上限が要らず、小数や負のステップも指定できます。
この記事では、公式ドキュメント(itertools.count、2026年10月18日確認)の仕様をもとに、基本の使い方、止め方、小数ステップの誤差、range()・enumerate()との使い分け、よく混同されるCounterとの違いを、Python 3.12で実行した結果つきで解説します。
itertools.count()の基本的な使い方
from itertools import count
c = count()
print(next(c), next(c), next(c))
print(c)
実行結果:
0 1 2
count(3)
next()を呼ぶたびに0, 1, 2…と返ります。print(c)すると、次に返す値がcount(3)のように表示されます。止めない限り値は永遠に増え続けます。
公式ドキュメントには、count()はおおよそ次のジェネレータと同じだと書かれています。
def count(start=0, step=1):
n = start
while True:
yield n
n += step
「startから始めて、stepを足し続ける」だけの単純な仕組みです。「呼ばれるたびに次の値を返す」イテレータの仕組みそのものは、「Python __next__とは?イテレータを自作する方法とStopIteration」で解説しています。
開始値(start)とステップ(step)を指定する
from itertools import count, islice
print(list(islice(count(1), 3)))
print(list(islice(count(10), 5)))
print(list(islice(count(0, 5), 5)))
print(list(islice(count(10, -2), 5)))
print(list(islice(count(start=1, step=2), 3)))
実行結果:
[1, 2, 3]
[10, 11, 12, 13, 14]
[0, 5, 10, 15, 20]
[10, 8, 6, 4, 2]
[1, 3, 5]
| 書き方 | 返す値 |
|---|---|
count() |
0, 1, 2, 3, … |
count(1) |
1, 2, 3, 4, … |
count(0, 5) |
0, 5, 10, 15, … |
count(10, -2) |
10, 8, 6, 4, …(減っていく) |
count(0, 0.5) |
0, 0.5, 1.0, 1.5, … |
ステップにマイナスを指定すると減っていきます。0を下回っても止まらない点に注意してください。
count()の止め方3通り(list()に直接渡さない)
いちばん危険な間違いは、count()をlist()にそのまま渡すことです。
from itertools import count
list(count()) # 絶対に実行しない
これは終わらない処理で、メモリを使い切るまで止まりません。sum()・max()・sorted()に渡した場合も同じです。必ず次のどれかで止めます。
| 止め方 | 書き方 | 向いている場面 |
|---|---|---|
| 件数で切る | islice(count(), 5) |
先頭からn個だけ欲しい |
| 条件で抜ける | for i in count(): ... break |
条件を満たす最初の値を探す |
| 有限のものと組む | zip(count(), データ) |
データに番号を振る |
件数で切る方法の詳細は「Python itertools.islice()とは?」を参照してください。
forとbreakで「条件を満たす最初の値」を探す
from itertools import count
for i in count(1):
if i * i > 50:
print("最初に2乗が50を超えるのは", i)
break
実行結果:
最初に2乗が50を超えるのは 8
range()で書くと上限を先に決める必要があり、足りなければ書き直しになります。上限が読めないときこそcount()です。while True:とカウンタ変数の組み合わせより、変数の更新し忘れが起きません。
zip()で番号を振る
from itertools import count
print(list(zip(count(1), "abc")))
print(list(zip(count(100, 10), ["a", "b", "c"])))
実行結果:
[(1, 'a'), (2, 'b'), (3, 'c')]
[(100, 'a'), (110, 'b'), (120, 'c')]
zip()は短いほうに合わせて終わるので、無限のcount()と組んでも安全に止まります(「Python zip()とは?」)。
小数のステップと誤差
range()は整数しか受け付けませんが、count()は小数も使えます。
from itertools import count, islice
print(list(islice(count(0, 0.5), 5)))
range(0, 3, 0.5)
実行結果:
[0, 0.5, 1.0, 1.5, 2.0]
TypeError: 'float' object cannot be interpreted as an integer
ただしcount()は足し算を繰り返すため、0.1のように2進数で正確に表せない値では誤差がたまります。
from itertools import count, islice
print(list(islice(count(0, 0.1), 4)))
print(list(islice(count(0, 0.1), 11))[-1])
print([0 + 0.1 * i for i in islice(count(), 11)][-1])
実行結果:
[0, 0.1, 0.2, 0.30000000000000004]
0.9999999999999999
1.0
10回足した結果は1.0になりませんでした。公式ドキュメントも、小数で数えるときは(start + step * i for i in count())のように掛け算で計算するほうが精度がよくなる場合があるとしています。3行目がその書き方です。誤差を許さない場面ではdecimal.Decimalやfractions.Fractionを渡すこともできます。
from decimal import Decimal
from itertools import count, islice
print(list(islice(count(Decimal("0.1"), Decimal("0.1")), 3)))
実行結果:
[Decimal('0.1'), Decimal('0.2'), Decimal('0.3')]
count()の実践例
連番のIDを自動で振る
from itertools import count
ids = count(1)
class User:
def __init__(self, name):
self.id = next(ids)
self.name = name
u1 = User("A")
u2 = User("B")
print(u1.id, u2.id)
実行結果:
1 2
グローバルなカウンタ変数を+= 1で更新するより短く、更新し忘れも起きません。
map()と組み合わせて数列を作る
from itertools import count, islice
print(list(map(lambda x: x * x, islice(count(1), 5))))
実行結果:
[1, 4, 9, 16, 25]
公式ドキュメントでも、count()はmap()で連続したデータを作ったり、zip()で番号を付けたりする用途が挙げられています。
range()・enumerate()との違いと使い分け
| 項目 | count() |
range() |
enumerate() |
|---|---|---|---|
| 終わり | なし(無限) | あり | 元データの長さ |
| 小数のステップ | 使える | 使えない | ステップ指定なし |
len()・[0] |
使えない | 使える | 使えない |
| 繰り返し使う | 一度きり | 何度でも | 一度きり |
| 向いている用途 | 上限が未定の探索、ステップ付きの番号 | 回数が決まった繰り返し | データに1ずつ番号を振る |
単純な番号付けならenumerate("abc", 1)のほうが読みやすく、結果もzip(count(1), "abc")と同じです。count()の出番は、上限が決まっていないときと、10ずつなどステップを変えて番号を振りたいときです。回数が決まっているなら「Python range()の使い方」で十分です。
よくあるエラーと混同
TypeError: object of type ‘itertools.count’ has no len()
from itertools import count
len(count()) # 1つ目
count()[0] # 2つ目
それぞれ単独で実行した結果:
TypeError: object of type 'itertools.count' has no len()
TypeError: 'itertools.count' object is not subscriptable
count()はイテレータなので長さもインデックスもありません。値はnext()かfor文で取り出します。
itertools.Counterは存在しない(collections.Counterと混同)
「要素の出現回数を数える」のはitertoolsではなくcollections.Counterです。
import itertools
itertools.Counter
実行結果:
AttributeError: module 'itertools' has no attribute 'Counter'
from collections import Counter
print(Counter("banana"))
実行結果:
Counter({'a': 3, 'n': 2, 'b': 1})
出現回数の数え方は「Python Counterの使い方」、文字列やリストのcount()メソッドは「Pythonのcount()とは?」で解説しています。itertools.count()は「数を数え上げる」もの、Counterと.count()は「個数を数える」もの、と覚えると区別しやすくなります。
itertools.count()のまとめ
count(start=0, step=1)はstartからstepずつ増える無限の連番count(1)で1始まり。ステップにマイナスや小数も指定できるlist()に直接渡すと終わらない。islice()・break・zip()で止める- 小数ステップは誤差がたまる。
start + step * iやDecimalで回避 - 単純な番号付けは
enumerate()、上限未定の探索はcount() - 出現回数を数えるのは
collections.Counter
よくある質問
Q. itertools.count(1)は何を返しますか?
1, 2, 3, … と1ずつ増える数を終わりなく返すイテレータです。最初の引数startが開始値で、ステップは省略すると1になります。
Q. count()を途中で止めるにはどうすればよいですか?
islice(count(), 5)のように件数で切るか、for文の中で条件を満たしたらbreakするか、zip()で有限のデータと組み合わせます。list(count())のようにそのまま全部を取り出そうとすると終わりません。
Q. range()とcount()の違いは何ですか?
range()は終わりがあり整数のみで、len()やインデックスも使えます。count()は終わりがなく、小数のステップも使えますが、len()やインデックスは使えません。回数が決まっているならrange()、上限が決まっていないならcount()です。
Q. itertools.Counterはありますか?
ありません。要素の出現回数を数えるクラスは collections.Counter です。import itertools のあとに itertools.Counter と書くと AttributeError になります。



