Pythonのobjectとtype(型)について整理した。 適切なデータ構造を選択したい。
type | class | mutable(not hashable) | immutable(hashable) | iterable |
---|---|---|---|---|
sequence | list | ○ | ○ | |
sequence | tuple | ○ | ○ | |
special sequence | string(※1) | ○ | ○ | |
range | range | ○ | ○ | |
mapping | dict | ○ | ○ | |
set | set | ○ | ○ | |
set | frozenset | ○ | ○ | |
int | int | ○ | ||
bool | bool | ○ | ||
float | float | ○ |
built-in object
- Pythonは標準組み込み (built-in) type (native data collection) として、 次の型等がある。
- int, string, list, dict, tuple
- built-in objectではmethodが使える。
- Pythonでは primitive type (プリミティブ型) は無い。
- property、 methodを持たない単純data。
- つまり、 methodが全て存在する。
- JavaScript等は、 primitive typeがある。
- 他にstring(文字列)、 boolean(論理値)等がある。
pythonにおけるcontainerについて
- 一部のsequence type (list,tuple), set, mapping type (dict) 等、 複数objectをまとめられるtype(型)をcontainer type (又はcollection type) と呼ぶ。
- 汎用組み込みcontainerとも呼ばれる。
- string sequence typeは含まれない (※1)。
- containerはobjectの参照列を指す。
- immutableなcontainerではpointer(reference値、 どのobjectを参照しているか)は変更出来ないが、 参照先のobject自体を変更することは出来る (※2)。
[]
(box brackets: 角括弧)経由等でcontainer内の要素にアクセスする。
iterableとiterator
Iteration
(繰り返し)は、 何かを次々に取り出す(loop)一般的な用語である。 Pythonでは、 iterable
と iterator
は特別な意味を持つ。
>>> iterable = "test" >>> iterator = iter(iterable) >>> next(iterator) 't' >>> next(iterator) 'e' >>> next(iterator) 's' >>> next(iterator) 't' >>> next(iterator) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>> iter(iterator) is iterator True >>> iterator <str_iterator object at 0x1087ad8d0>
iterator
__next__()
と__iter__()
methodを持つobject。- for, map, list内包表記等を使用する場合は まず
__iter__()
を呼び出してiteraterを作り、次にiteraterの__next__()
methodが呼び出され、 状態を記憶しつつfor loopの次の値を返す(次の値をpointingするようstateを更新する)。- 要は1要素取り出す度に処理を行い、 状態を記憶して要素を返す(生成する)。
next()
でiteratorが進む (__next__()
が呼び出されている)。
- container object (要素) が無くなった場合、
StopIteration
exceptionを発生させ、 完了したことを通知する。
def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index]
- container type, string typeは全てiterable。
- listはiterableなobjectだが、 iteratorでは無い。
- yieldを利用した実装を示すことが多い。
- generater objectもiteratorの一種。
>>> test_li = [1, 2, 3] >>> test_li_iter = iter(test_li) >>> test_li_iter.__iter__() <list_iterator object at 0x1087ad780>
9.8. Iterators docs.python.org
iterable
- loopしてforで回せるもの。
- for loopのin右側に来る要素
for x in iterable:
- 要素を1度に1つずつ返すことが出来るobject。
- 新しいiteratorを返す
__iter__()
methodを定義するobject。- 若しくは (0から始まるsequential indexを取得可能な) index検索に適した
__getitem__()
methodを持つobject。- indexが無効になった場合、
IndexError
exceptionが発生する。
- indexが無効になった場合、
- 若しくは (0から始まるsequential indexを取得可能な) index検索に適した
- iterableなobjectとして以下がある。
- sequence type(list, tuple, string)
- non sequence type(dict, file object)
__iter__()
で呼び出すことが出来て、 iteratorを返すobject全て。
# int object is not iterable。 >>> test_int = 100 >>> test_int_iter = iter(test_int) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable # list object is iterable. >>> test_li = [1,2,3] >>> test_li_iter = iter(test_li) >>> next(test_li_iter) 1 >>> next(test_li_iter) 2 >>> next(test_li_iter) 3 >>> next(test_li_iter) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration # dictionary object is iterable. >>> test_dict = {"key_1":"val_1","key_2":"val_2"} >>> test_dict_iter = iter(test_dict) >>> next(test_dict_iter) 'key_1' >>> test_tuple = (1,2,3) >>> test_tuple_iter = iter(test_tuple) >>> next(test_tuple_iter) 1 >>> test_str = "aaa bbb" >>> test_str_iter = iter(test_str) >>> next(test_str_iter) 'a'
sequence type
以下の特徴がある。
- 複数の要素をまとめて扱える。
- string, tuple, list, range がある。
- 要素は順序付けされる。
mutable, immutable
Pythonには、 mutable(変更可能)、 immutable(変更不可能)な型がある。 変数はobjectへのpointer(reference値)を格納しており、 object自体を格納していない。 その為、 objectはimmutableであっても、 pointer(reference値)自体は変更可能。
>>> test_li = [1,2,3] # id ≒ pointer >>> id(test_li) 4437242312 >>> test_li_2 = test_li >>> id(test_li_2) 4437242312 >>> test_li_2 [1, 2, 3]
変数は違えど、 同じpointer(reference値)である。
- mutable
- 要素を変更可能なobject。
- dict, set, list 等。
- hashableでは無い為、 dictのkeyには利用不可である。
- immutable
- 要素が変更不可能なobject。
- 変更するには、 pointer(reference値)が異なる新しいobjectを作成する必要がある。
- string, tuple, frozenset, int, range 等。
- hashableであるので、 dictのkeyには利用可能である。
hashable type
- immutableな組み込み型は全てhashable。
- tuple等。
- list, dict, 集合はmutableであり、hashableではない。
- dictのkeyに使うことは出来ない。
注釈
※1. string sequence(文字列型)は他のsequence typeと異なり、 immutable(不変)でありcontainerでは無い。
>>> a = 'xxx' >>> b = 'yyy' >>> print(a) xxx >>> a = a + b >>> print(a) xxxyyy
上記はaが xxxyyy に変化したように見える。 しかしa自体は xxx のままである。 最初に変数aのpointer(reference値)はxxxを指していたが、 xxx+yyy を指すようにpointer (references先、 向き先) を変更したのだ。 stringはimmutable(不変)だが、 pointerを変更することは出来る。
※2. immutableなtupleの変数(pointer、 reference値)は変わらずとも、 object自体はmutableである。
>>> test_tuple = ([1],[2],[3]) >>> id(test_tuple) 4437171656 >>> test_tuple[0].append(4) >>> test_tuple ([1, 4], [2], [3]) >>> id(test_tuple) 4437171656