2012-04-17 5 views
3

辞書としては、switchという形で、辞書にはブール値を設定するのが好きです。例:else/default場合など辞書をPython 2.7.3のswitch文として使用する

>>> def f(a): 
...  return {True: -a, a==0: 0, a > 0: a}[True] 
... 
>>> f(-3) 
3 
>>> f(3) 
3 
>>> f(0) 
0 

キーTrue作品や、他のキーがTrueに評価されていない場合にのみ返されます。私はこれを推測していますが、辞書を反復するための何らかの評価順序を前提としています。

は今枝2.6、2.7、3.1および3.2の最新バージョンの最新release announcement from the Python teamから次の抜粋を見て:

ハッシュのランダム化がdictsの反復順序を引き起こし、 予測不可能であることを設定し、異なりますPythonを実行している間。 Pythonは、dictまたはset内のキーの反復順序を と決して保証しておらず、アプリケーション は決してそれに依存しないように勧められます。歴史的には、辞書の反復順序 はリリース間で頻繁に変更されておらず、Pythonの連続実行間では常に のままです。したがって、一部の 既存のアプリケーションは、dictまたはset orderingに依存している可能性があります。

これは、スイッチ呼び出しとしてdictsを使用することはもはや不可能であるということですか?あるいは、別のクラス(OrderedDictなど)を使用する必要がありますか?または、私は完全にオフになっていて、これはまったく影響しませんか?

+2

スニペットに_iteration_はありません。あなたは影響を受けません。 – georg

答えて

6

このコードの仕組みが誤解されました。

辞書には、TrueFalseという2つのキーしかありません。 Trueキーに複数の競合する値が存在する可能性がありますが、辞書の初期化時に解決されます。

辞書ルックアップの繰り返しはありません。

+0

ありがとうございました。あなたの答えは、私が最終的にこのコードの仕組みを理解できるようにしました。 – rahmu

3

辞書を使用して条件をハッシュする方法は、注文の影響を受けません。あなたは厳密に辞書にアクセスするためにキーを使用しており、キー/値の繰り返しをしていないので、順序は重要ではありません。だからあなたの辞書のあなたの特定の使い方は、Pythonの辞書ハッシュランダム化の影響を受けません。

5

ハッシュランダム化はアプリケーションに影響を与えません。辞書内のキーの反復順序に依存するアプリケーションにのみ影響するはずです。

しかし、あなたのテクニックは単純なif..elifチェーンよりも不明瞭であり、効率が悪い(新しいdictを作成するのは安くない)ことがわかりました。

0

あなたの例では反復処理を使用していないので、コードは安全です。

しかし、あなたの解決策はちょっと変わっていますが、booleanというキーは読みにくくありません。

あなたがしようとしないのはなぜ:

switch = { 
    choice1: func1 
    choice1: func2 
    ... 
} 

と:

switch[variable]() 
1

をこれは非常に汚いコードである私がPythonのでは動作しますが、辞書とラインを(読み取りに数分かかります3年)、これはデバッグが非常に難しくなります。次のデベロッパー(読者:半年で読んでください)はこれを読むことができません。あなたがそれらを必要とする場合

スイッチ構築物は、コールバックの辞書に置き換えることができます:

{value1: one_func, value2: another_func, value3: third_func} 

あなたが偽/唯一の真が必要な場合は、あなたがどのような構造を必要としない:

return one_func() if check else another_func() 

多くの場合、スイッチはifの連鎖で置き換えることができます...返信:

if check: 
    return one_func() 

return another_func() if another_check else third_func() 

これらはすべて、適切かつデバッグ可能。

2

辞書が左から右の順序で構築されていることを前提として、これはおそらく動作します。順序付けされていない反復についてのポイントは、辞書が構築された後では、構築プロセス自体ではなく、それを反復するのではなく、索引付けされています。

しかし、率直に言って、この動作に頼るのは良い考えではありません。ケースの評価の順序が効果的に右から左にあるため(つまり、右から左へ)、仮定された動作に依存しているため(脆弱であることは保証されているかもしれませんが)最も真のケースが勝つ)。次のようにはるかに分かりやすいソリューションです:あなたはのようなものをやっている場合にのみ、あなたに影響を与えます

return (a if a > 0 else 
     0 if a == 0 else 
     -a) 
0

mydict.values()[0] 

そして、これに頼っては常に同じ値になるように。あなたが引用した文書は、それが起こることが保証されていないと言います。

ただし、コードには考慮する必要のある問題が1つあります。これは短絡に関連しています。そうした場合:

if a == 0: 
    return 0 
elif a > 0: 
    return a 
else: 
    return -a 

あるいは、より簡潔に(しかし、おそらくあまり読み取り可能)return 0 if a == 0 else a if a > 0 else -aを、aは0で、その後、a > 0が評価されることはありません(とあなたがそれ以上のreturnがいない場合でも、まだできません) 。あなたの辞書は、毎回の条件であるとして与えたすべての鍵を評価する必要があります。 ifの代わりに辞書ディスパッチを試みる唯一の理由は効率ですが、キーが一定ではなく、辞書全体が事前計算可能である場合、あなたはひどく敗北する可能性があります。 、あなたの質問への答えは明白なことを念頭に置いて

def f(a): 
    d = {} 
    d[True] = -a 
    d[a==0] = 0 
    d[a>0] = a 
    return d[True] 

次のようになります。

2

まず、あなたのコードは、多かれ少なかれ同等にされていることを実感。

なぜこの単純な構文ではなく、わかりにくい構文を使用していますか? でもこれは、より読みやすいです:

def f(a): 
    return a if a > 0 else 0 if a == 0 else -a 

あなたのコードは本当にあなたが何か間違ったことをやっている明確なサインでなければなりませんやっていることを誤解しているようだという事実。

関連する問題