Python 3.0-dictメソッドがビューを返す-なぜ?
-
19-08-2019 - |
質問
dictメソッドdict.keys()、dict.items() およびdict.values()return <!>#8220; views <!>#8221; リストの代わりに。 http://docs.python.org/dev/3.0/whatsnew//3.0 .html
まず、ビューとイテレーターの違いは何ですか?第二に、この変更の利点は何ですか?パフォーマンス上の理由だけですか?
それは私には直感的ではないようです。つまり、私は物のリストを求めています(すべてのキーを渡してください)。これは人々を混乱させますか?
解決
実質的にリストを取得しています。これは単に内部リストのコピーではなく、リストがあるが内部状態のみを表すかのように動作するものです。
それはJavaで実装されているのと同じ方法です(おそらく他の多くの言語/環境も同様です)。
主な理由は、多くのユースケースでは、完全に切り離されたリストを返すことは不要で無駄です。コンテンツ全体をコピーする必要があります(多くの場合とそうでない場合があります)。
単にキーを反復処理する場合は、新しいリストを作成する必要はありません。そして、本当にそれを別のリストとして(コピーとして)必要とするなら、ビューからそのリストを簡単に作成できます。
他のヒント
Joachim Sauerの答えは、list
が返されない理由を非常によく説明しています。しかし、Python 2でiteritems
などが行ったように、これらの関数がイテレーターを返さない理由は疑問です。
イテレータは、コンテナよりもはるかに制限的です。たとえば、イテレータは複数のパスを許可しません。 2回目のパスを試すと、空であることがわかります。したがって、コンテナではelem in cont
などの操作がサポートされていますが、イテレータではサポートできません。要素が<!> quot; in <!> quot;イテレーター、イテレーターは破壊されます!
一方、コンテナを取得するには、通常、辞書のキーからリストを作成するなどのコピーを作成する必要があります。
view
オブジェクトには両方の長所があります。コンテナとして動作しますが、辞書のコピーは作成しません。実際、これは、基礎となる辞書にリンクすることで機能する一種の仮想読み取り専用コンテナーです。標準のPythonの他の場所で見られるかどうかはわかりません。
編集:
@AntonyHatchkins:ジェネレーター関数を返さない理由は、高速のin
操作を許可しないためです。はい、n
はジェネレータ関数に対して機能します(それらを呼び出すとき)。つまり、これを行うことができます:
def f():
for i in range(10):
yield i
5 in f() # True
ただし、O(n)
の定義によれば、右側がジェネレーターである場合、PythonはジェネレーターのすべてのO(1)
アイテムを通過します。これにより、<=>時間の複雑さが生じます。それが任意のジェネレーターにとって唯一の意味のある動作であるため、あなたはそれについて何もすることができません。
>>> d = dict(zip(range(50000000), range(50000000)))
>>> 49999999 in d
True
>>> 49999999 in iter(d) # kinda how generator function would work
True
>>>
および最初の<=>が2番目の<=>と比較される速度に注目します。
関連する質問で既に述べたように、ビューにはlen()
メソッドがありますが、イテレータにはありません(リストにはあります)。
リストの代わりにビューを返す別の利点は、少なくともキーに対して、リスト(またはイテレータ)のO(N)ではなく、O(1)操作で最適化されたメンバーシップテストがあることです。