callable() / iter() / next()
| 対応: | Python 2(2000) |
|---|
オブジェクトが呼び出し可能かどうかの確認や、イテレータの作成・手動での要素取得を行う組み込み関数です。
構文
# オブジェクトが呼び出し可能(関数・クラスなど)か確認する callable(オブジェクト) # イテラブルからイテレータを作成する iter(オブジェクト) iter(呼び出し可能オブジェクト, 番兵値) # イテレータから次の要素を取得する next(イテレータ, デフォルト値) # オブジェクトのハッシュ値を返す hash(オブジェクト)
関数一覧
| 関数 | 概要 |
|---|---|
| callable(obj) | オブジェクトが呼び出し可能であれば True を返します。関数・クラス・__call__ を持つオブジェクトが対象です。 |
| iter(obj) | イテラブルオブジェクトからイテレータを生成します。2引数形式では番兵値(sentinel)まで繰り返し呼び出します。番兵値とは、繰り返し処理を終了させるための特別な値のことです。 |
| next(iterator, default) | イテレータの次の要素を返します。要素がなくなったとき、default を指定していれば返し、なければ StopIteration を発生させます。 |
| hash(obj) | オブジェクトのハッシュ値(整数)を返します。辞書のキーやセットの要素に使えるオブジェクトが対象です。 |
サンプルコード
callable_iter_next.py
# callable() でオブジェクトが呼び出し可能か確認する
def greet():
return "こんにちは"
print(callable(greet)) # True(関数は呼び出し可能)
print(callable(42)) # False(整数は呼び出せない)
print(callable(str)) # True(クラスは呼び出し可能)
print(callable(print)) # True(組み込み関数も呼び出し可能)
# __call__ を持つオブジェクトも呼び出し可能
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
triple = Multiplier(3)
print(callable(triple)) # True
print(triple(5)) # 15
# iter() と next() でリストを手動で反復する
members = ["岡部倫太郎", "牧瀬紅莉栖", "椎名まゆり"]
it = iter(members)
print(next(it)) # 岡部倫太郎
print(next(it)) # 牧瀬紅莉栖
print(next(it)) # 椎名まゆり
# print(next(it)) # StopIteration が発生する
# デフォルト値を指定すると例外が発生しない
it2 = iter(members)
print(next(it2, "なし")) # 岡部倫太郎
print(next(it2, "なし")) # 牧瀬紅莉栖
print(next(it2, "なし")) # 椎名まゆり
print(next(it2, "なし")) # なし(要素がなくなった)
# iter() の2引数形式:番兵値が返るまで関数を繰り返し呼び出す
import random
# random.randint が 6 を返すまで繰り返す疑似サイコロ
rolls = list(iter(lambda: random.randint(1, 6), 6))
print(f"{len(rolls)}回で 6 が出ました。")
# hash() でオブジェクトのハッシュ値を確認する
print(hash("hello")) # 文字列のハッシュ値(実行ごとに変わります)
print(hash(42)) # 42(整数のハッシュ値は値そのものになることが多い)
print(hash((1, 2, 3))) # タプルはハッシュ可能
# print(hash([1, 2, 3])) # TypeError: リストはハッシュ不可能
実行すると次のように出力されます。
python3 callable_iter_next.py True False True True True 15 岡部倫太郎 牧瀬紅莉栖 椎名まゆり 岡部倫太郎 牧瀬紅莉栖 椎名まゆり なし N回で 6 が出ました。 # 実行ごとに変わります -3550055125485641917 # 実行ごとに変わります 42 529344067295497451 # 実行ごとに変わります
よくあるミス
よくあるミス1: StopIterationの捕捉忘れ
『next()』はイテレータが尽きると『StopIteration』を発生させます。デフォルト値(第2引数)を指定しないと例外が発生します。
items = iter([1, 2]) next(items) # 1 next(items) # 2
次のように記述します。
# イテレータが尽きると StopIteration が発生する
try:
next(items)
except StopIteration:
print('イテレータが尽きました')
次のように記述します。
# デフォルト値を指定する result = next(items, None) # None が返る(例外なし) print(result) # None
よくあるミス2: callableで関数に()を付けてしまう
『callable()』は「オブジェクトが呼び出し可能か」を確認する関数です。引数に関数を渡すときは、実行しない(括弧を付けない)ことが必要です。
def greet(name):
return f'こんにちは、{name}!'
# 括弧を付けると関数を実行してしまう(Noneになる)
print(callable(greet())) # TypeError: argument of type 'str' is not callable
次のように記述します。
# 括弧なしでオブジェクト自体を渡す print(callable(greet)) # True print(callable(42)) # False
よくあるミス3: __iter__なしでイテレータを作る
カスタムイテレータは『__iter__』と『__next__』の両方が必要です。『__next__』だけでは for 文での使用や他のイテレータ関数との連携が動作しません。
# __iter__ がないと for 文で使えない
class BadCounter:
def __init__(self, max_val):
self.current = 0
self.max_val = max_val
def __next__(self):
if self.current >= self.max_val:
raise StopIteration
self.current += 1
return self.current
# for x in BadCounter(3): # TypeError: 'BadCounter' object is not iterable
次のように記述します。
# __iter__ も実装する
class GoodCounter:
def __init__(self, max_val):
self.current = 0
self.max_val = max_val
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max_val:
raise StopIteration
self.current += 1
return self.current
for x in GoodCounter(3):
print(x) # 1, 2, 3
概要
Pythonのfor文は内部で『iter()』でイテレータを作成し、『next()』を繰り返し呼び出して『StopIteration』が発生したらループを終了しています。この仕組みを理解することで、ジェネレータやカスタムイテレータの挙動が理解しやすくなります。
『next()』でデフォルト値を指定しない場合、イテレータが空になると『StopIteration』例外が発生します。ループ外で『next()』を使う場合は必ずデフォルト値を指定するか、try-except で例外を捕捉します。
『hash()』はリストや辞書など、変更可能(ミュータブル)なオブジェクトには使えません。辞書のキーやセットの要素に使えるのはハッシュ可能(イミュータブル)なオブジェクトだけです。独自クラスでハッシュを有効にするには『__hash__()』メソッドを実装します。ファイルを反復処理する場合は『open()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。