len()関数のコスト


回答:


341

あなたが言及したすべてのタイプとその他のタイプのO(1)(要素の実際の長さに依存しない一定の時間-非常に速い)です。setarray.array


17
役立つ回答をありがとう!これが当てはまらないネイティブ型はありますか?
mvanveen 2012年


84

これらのオブジェクトはすべて、それぞれの長さを追跡します。長さを抽出する時間は短く(big-O表記のO(1))、ほとんどが[大まかな説明、C用語ではなくPython用語で書かれています]:辞書で「len」を検索し、それをオブジェクトの__len__メソッドを検索してそれを呼び出すbuilt_in len関数...必要なのはreturn self.length


3
これは、実装の詳細への洞察を与えるため、これが最も適切な答えだと思います。
AK

なぜlength辞書に表示されないのdir(list)ですか?
ViFI

これが私が探していたものです
Visakh Vijayan

@ViFIこれは単なる例です。説明list.lenghtされている変数は、PythonではなくCで実装されています。
コワルスキー

73

以下の測定は、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

辞書(2.7以上で利用可能な辞書-理解):

$ 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

セット(2.7以上で利用可能なset-comprehension):

$ 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

Deque:

$ 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

1
これは、私たちがすでに知っていることを示していますが、ベンチマークにはあまり適していません。これは、range(10)およびrange(1000000)がO(1)であると想定されていないためです。
不明

3
これは断然最良の答えです。誰かが一定の時間を理解していない場合に備えて、結論を追加する必要があります。
santiagobasulto 2013年

4
コメントをありがとう。のO(1)の複雑さに関するメモを追加しlen()-sフラグを適切に使用するように測定値を修正しました。
Mechanical_Meat

長さを変数に保存すると、計算時間を大幅に節約できることに注意することが重要です: 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ナノ秒
ラドスティンストヤノフ

16

lenはO(1)です。RAM内では、リストはテーブル(一連の連続したアドレス)として保存されます。テーブルがいつ停止するかを知るには、コンピュータには長さと開始点の2つが必要です。そのため、len()はO(1)であり、コンピューターは値を格納するため、検索するだけで済みます。


3

Pythonのlen()はリストのサイズに依存すると考えていたので、複数回使用する場合は常に長さを変数に格納します。しかし、今日デバッグしているときに、リストオブジェクトの__len__属性に気づいたので、len()はそれをフェッチしているだけである必要があり、複雑さはO(1)になります。だから、誰かがすでにそれを尋ねて、この投稿に出くわしたなら、私はググっただけです。


しかし、これ__len__は関数であり、リストの長さを表す変数ではありません。
コワルスキー

@Kowalskiはいlenは関数ですが、機能はすべてself.lengthを返します
AYUSH SENAPATI

しかし、あなたの投稿はそれについて何も語っていません。また、list.__len__関数が一定の時間で実行されていることをどのようにして知っていますか?それは機能しますが、それが機能であるというだけではありません。そのように実装したからです。
Kowalski
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.