回答:
in
間違いなくもっとpythonicです。
keys()
、コピーではなくディクショナリへのセットに似たビューなのでx in d.keys()
、O(1)も同様です。それでも、x in d
よりPythonicです。
x in d.keys()
それは、x in d.keys()
算術演算(ハッシュの計算)を実行し、ルックアップを実行するだけの一時的なオブジェクトを作成して破棄する必要があるためです。これd.keys()
は約10倍の長さにすぎないことに注意してください。私はチェックしていませんが、それがO(1)だけであると確信しています。
in
優雅なだけでなく(そして非推奨ではない)だけでなく、パフォーマンスでもハンズダウンで勝利します。例:
$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'
10000000 loops, best of 3: 0.0983 usec per loop
$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'
1000000 loops, best of 3: 0.21 usec per loop
次の観察は常に正しいとは限りませんが、通常、Pythonでは高速なソリューションの方がエレガントでPythonicであることがわかります。それ-mtimeit
がとても役立つ理由です-それはあちこちに100ナノ秒を節約するだけではありません!-)
has_key
O(1)のようにも見えます。
使用dict.has_key()
あなたのコードは、以前の(2.3よりもPythonのバージョンで実行可能であることが必要である(および場合のみ)場合key in dict
導入されました)。
in
実際にパフォーマンスを低下させる1つの例があります。
あなたが使用している場合はin
O(1)コンテナにのみ実装__getitem__
し、has_key()
が、ではない__contains__
(とあなたはO(1)O(N)の検索に検索を向けるだろうin
経由で線形検索にフォールバック__getitem__
)。
修正は明らかに簡単です:
def __contains__(self, x):
return self.has_key(x)
has_key()
あるPythonの2の辞書に固有。in
/ __contains__
は使用する正しいAPIです。フルスキャンが避けられないコンテナの場合、いずれにしてもhas_key()
メソッドはありません。O(1)のアプローチがある場合、それはユースケース固有であり、開発者が問題に適したデータ型を選択する必要があります。
has_key
はディクショナリメソッドですがin
、任意のコレクションで機能し、__contains__
見つからないin
場合でも、他のメソッドを使用してコレクションを反復処理して調べます。
in
テストを行うことは実際には非常に効率的range
です。xrange
ただし、Python 2 での効率についてはよくわかりません。;)
__contains__
を簡単に計算できます。
range
毎回新しいインスタンスを作成するオーバーヘッドが含まれます。単一の既存のインスタンスを使用すると、「範囲内の整数」テストは私のタイミングで約40%速くなります。
dict.has_key()のソリューションは非推奨です。「in」を使用してください-崇高なテキストエディター3
ここでは、「年齢」という名前の辞書の例を取り上げました-
ages = {}
# Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).
if 'Sue' in ages:
print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
print "Sue is not in the dictionary"
アダム・パーキンのコメントでアレックス・マーテリのパフォーマンステストを拡大しています...
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in main
x = t.timeit(number)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
d.has_key(12)
AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d'
10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'
10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d.keys()'
10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'
10000000 loops, best of 3: 0.117 usec per loop
このようなものがあれば:
t.has_key(ew)
Python 3.X以降で実行するには、以下に変更します。
key = ew
if key not in t
t.has_key(ew)
返されます。値が辞書にない場合に返されます。さらに、エイリアスは非常に冗長です。正しいスペルはです。これは、8年前に受け入れられた回答がすでにあなたに言ったことです。True
ew
key not in t
True
key = ew
if ew in t