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として機能し、他のキーが評価されない場合にのみ返されます。これは、辞書を反復するためのある種の評価順序を前提としていると思います。elsedefaultTrue

次に、ブランチ2.6、2.7、3.1、および3.2の最新バージョンについて、Pythonチームからの最新リリース発表からの次の抜粋を見てください。

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

これは、スイッチ呼び出しとしてdictを使用できなくなることを意味しますか?それとも、他のクラス(OrderedDictまたは何か)を使用する必要がありますか?または多分私は完全にオフであり、それはこれにまったく影響を与えるべきではありませんか?

4

8 に答える 8

6

このコードがどのように機能するかを誤解しました。

辞書には2つのキーしかありません:TrueFalse。キーには複数の競合する値が存在する可能性がありTrueますが、それはディクショナリの初期化時に解決されます。

辞書検索の反復はありません。

于 2012-04-17T08:00:54.393 に答える
5

ハッシュのランダム化はアプリケーションに影響しません。ディクショナリ内のキーの反復順序に依存するアプリケーションにのみ影響するはずです。

そうは言っても、あなたのテクニックは単純なチェーンよりも曖昧であり、if..elif効率も低いと思います(新しいdictを構築するのは安くはありません)。

于 2012-04-17T08:00:56.203 に答える
3

辞書を使用して条件をハッシュする方法は、順序の影響を受けません。ディクショナリにアクセスするために厳密にキーを使用しており、キー/値を反復処理していないため、順序は重要ではありません。したがって、辞書の特定の使用法は、Pythonの辞書ハッシュランダム化の影響を受けません。

于 2012-04-17T08:00:16.730 に答える
2

辞書が左から右の順序で作成されていることを前提とすると、これはおそらく引き続き機能します。順序付けられていない反復に関するポイントは、ディクショナリが構築された後のトラバーサルに関するものであり、構築プロセス自体ではありません。いずれにしても、ディクショナリを反復処理するのではなく、インデックスを作成します。

しかし率直に言って、この振る舞いに頼るのは良い考えではありません。想定される動作に依存しているため(おそらくこれを保証するものが仕様に含まれているため)、脆弱であり、ケースの評価の順序が事実上右から左(つまり、右-最も本当の場合が勝ちます)。はるかにわかりやすい解決策は次のとおりです。

return ( a if a > 0  else
         0 if a == 0 else
        -a)
于 2012-04-17T08:06:33.113 に答える
2

まず、コードが多かれ少なかれ同等であることを理解してください。

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

それを念頭に置いて、あなたの質問への答えが明らかになります。

単純なものではなく、なぜこのあいまいな構文に悩まされるのですか? これでさえもっと読みやすいです:

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

コードが実際に何をしているのかを誤解しているように見えるという事実は、何か間違ったことをしていることを明確に示しているはずです。

于 2012-04-17T08:10:13.817 に答える
1

これは非常に汚いコードであり、辞書の行を読むのに数分かかります(ただし、私はPythonで3年間作業しています)。これは、デバッグが非常に困難です。次の開発者(読んでください:半年後にあなた自身)はこれを読むことができなくなります。

switch構文は、必要に応じて、コールバックのdictに置き換えることができます。

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

True / Falseのみが必要な場合は、構造は必要ありません。

return one_func() if check else another_func()

多くの場合、スイッチはif...returnのチェーンに置き換えることができます。

if check:
    return one_func()

return another_func() if another_check else third_func()

これらはすべて、はるかに読みやすく、デバッグ可能です。

于 2012-04-17T08:04:29.960 に答える
0

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

booleanただし、キーがあまり読みにくいため、ソリューションは少し奇妙です。

試してみませんか:

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

と:

switch[variable]()
于 2012-04-17T08:01:40.960 に答える
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は効率ですが、キーが一定でなく、辞書全体が事前計算可能である場合、ひどく失う可能性があります。

于 2012-04-17T08:07:41.303 に答える