/tmp/log/cha_pppo

i love 玄米パン あんなし

Python: objectとtype(型)について

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では、 iterableiterator は特別な意味を持つ。

>>> 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が発生する。
  • 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