回答:
あなたが言及したすべてのタイプとその他のタイプのO(1)(要素の実際の長さに依存しない一定の時間-非常に速い)です。set
array.array
これらのデータ型でlen()を呼び出すのは、Python言語の最も一般的な実装であるCPythonの O(1)です。CPythonのさまざまな関数のアルゴリズムの複雑さを提供する表へのリンクは次のとおりです。
これらのオブジェクトはすべて、それぞれの長さを追跡します。長さを抽出する時間は短く(big-O表記のO(1))、ほとんどが[大まかな説明、C用語ではなくPython用語で書かれています]:辞書で「len」を検索し、それをオブジェクトの__len__
メソッドを検索してそれを呼び出すbuilt_in len関数...必要なのはreturn self.length
length
辞書に表示されないのdir(list)
ですか?
list.lenght
されている変数は、PythonではなくCで実装されています。
以下の測定は、len()
よく使用されるデータ構造のO(1)である証拠を提供します。
に関する注意timeit
:-s
フラグが使用され、2つの文字列がtimeit
最初の文字列に渡される場合、1回だけ実行され、時間は計測されません。
$ python -m timeit -s "l = range(10);" "len(l)"
10000000 loops, best of 3: 0.0677 usec per loop
$ python -m timeit -s "l = range(1000000);" "len(l)"
10000000 loops, best of 3: 0.0688 usec per loop
$ python -m timeit -s "t = (1,)*10;" "len(t)"
10000000 loops, best of 3: 0.0712 usec per loop
$ python -m timeit -s "t = (1,)*1000000;" "len(t)"
10000000 loops, best of 3: 0.0699 usec per loop
$ python -m timeit -s "s = '1'*10;" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop
$ python -m timeit -s "s = '1'*1000000;" "len(s)"
10000000 loops, best of 3: 0.0686 usec per loop
$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(10))};" "len(d)"
10000000 loops, best of 3: 0.0711 usec per loop
$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(1000000))};" "len(d)"
10000000 loops, best of 3: 0.0727 usec per loop
$ python -mtimeit -s"import array;a=array.array('i',range(10));" "len(a)"
10000000 loops, best of 3: 0.0682 usec per loop
$ python -mtimeit -s"import array;a=array.array('i',range(1000000));" "len(a)"
10000000 loops, best of 3: 0.0753 usec per loop
$ python -mtimeit -s"s = {i for i in range(10)};" "len(s)"
10000000 loops, best of 3: 0.0754 usec per loop
$ python -mtimeit -s"s = {i for i in range(1000000)};" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop
$ python -mtimeit -s"from collections import deque;d=deque(range(10));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop
$ python -mtimeit -s"from collections import deque;d=deque(range(1000000));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop
len()
、-s
フラグを適切に使用するように測定値を修正しました。
python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"
ループあたり223ナノ秒python -m timeit -s "l = range(100);" "len(l)"
66.2ナノ秒
Pythonのlen()はリストのサイズに依存すると考えていたので、複数回使用する場合は常に長さを変数に格納します。しかし、今日デバッグしているときに、リストオブジェクトの__len__属性に気づいたので、len()はそれをフェッチしているだけである必要があり、複雑さはO(1)になります。だから、誰かがすでにそれを尋ねて、この投稿に出くわしたなら、私はググっただけです。
__len__
は関数であり、リストの長さを表す変数ではありません。
list.__len__
関数が一定の時間で実行されていることをどのようにして知っていますか?それは機能しますが、それが機能であるというだけではありません。そのように実装したからです。