「TypeError: 'int' object is not iterable」の原因と解決方法を紹介します
結論
iterableでないint型のオブジェクトをiterableとして扱おうとしているため発生しているエラーです。
よくあるミスとしてはint型をfor文で回してしまった以下のようなプログラムです。
sample_int = 10
# iterableではないintのオブジェクトをfor文で利用
# TypeError: 'int' object is not iterable
for index in sample_int:
print(index)
解説
iterableとは
iterableの定義をPython公式ドキュメントの用語集から確認します。
(反復可能オブジェクト) 要素を一度に 1 つずつ返せるオブジェクトです。
反復可能オブジェクトの例には、(list, str, tuple といった) 全てのシーケンス型や、
dictやファイルオブジェクトといった幾つかの非シーケンス型、
あるいはSequence意味論を実装した__iter__()メソッドか__getitem__()メソッドを持つ
任意のクラスのインスタンスが含まれます。
説明だけ聞くとなかなか複雑に思えますが、要はfor文を回せるオブジェクトがiterableです。
list, dict, taple, stringなどがiterableに該当します。
少し意外ですが、stringをfor文で回すと1文字ずつ取得できます。
sample_list = [1, 2, 3]
sample_dict = {'a':1, 'b':2, 'c':3}
sample_taple = {1, 2, 3}
sample_string = 'あいう'
for item in sample_list:
print(item)
# 1
# 2
# 3
for item in sample_dict:
print(item)
# a
# b
# c
for item in sample_taple:
print(item)
# 1
# 2
# 3
for item in sample_string:
print(item)
# あ
# い
# う
iterableの判断方法
iterableであるか否かはitaratorを生成できるか否かで判断できます。
そのため下記のようなプログラムで判断可能です。
def IsIterable(object):
'''
objectがiterableかどうかを判断する
True:iterable, False:not iterable
'''
res = False
try:
iterator = iter(object)
res = True
except TypeError as te:
print('This object is not iterable. obj:', object)
res = False
return res
sample_list = [1, 2, 3]
sample_float = 1.0
print(IsIterable(sample_list))
# True
print(IsIterable(sample_float))
# This object is not iterable. obj: 1.0
# False
__getitem__()メソッドを持つオブジェクトは必ずしもiterableではない
iterableの定義に下記のような記述があります。
__getitem__()メソッドを持つ任意のクラスのインスタンスが含まれます。
しかし、注意すべきは必ずしもiterableではない点です。
このためhasattr(obj, "__getitem__")
で確認すると思わぬ不具合を招きます。
例えば、下記のようなクラスはiterableではありませんが、__getitem__()メソッドを持つオブジェクトです。
class NotIterable:
def __getitem__(self, str):
if str == 'a':
return 1
if str == 'b':
return 2
else:
raise KeyError
not_iterable = NotIterable()
print(not_iterable['a']) # 1
print(hasattr(not_iterable, '__getitem__')) # True
# __getitem__を持つが反復不可
# KeyError
for item in not_iterable:
print(item)
一方で、下記のようなクラスはiterableで、__getitem__()メソッドを持つオブジェクトです。
class Iterable:
def __getitem__(self, int_obj):
return int_obj * 2
iterable = Iterable()
print(iterable[1]) # 2
print(hasattr(iterable, '__getitem__')) # True
# __getitem__を持つが反復可
for item in iterable:
print(item)
# 0
# 2
# 4
# 6
# ...
このようにkeyにint以外を定義した場合
__getitem__()メソッドを持つオブジェクトでありながらiterableでないオブジェクトとなります。
0 件のコメント :
コメントを投稿