9

どちらがより良い最適化ですか?

  • 'string'を受け取る一連のif/elseステートメントは、それに適切な関数を返します。(約40-50 if / elseステートメント)。
  • キーと値のペアを維持する辞書。文字列としてのキー、関数オブジェクトとしての値、および関数オブジェクトを検索して返すための1つのメイン関数。

上記のメソッドを使用して実際に関数オブジェクトを返すメイン関数は、数百万回または数十億回呼び出されるため、これをインテリジェントに行う必要があります。より良い方法は何でしょうか?

例えば

dict['str1'] = func1
dict['str2'] = func2
and so on..

def main_func(str):
    return dict[str]

または

def main_func(str):
    if 'str1':
      return func1
    elif 'str2':
      return func2

どちらがいいでしょう..?そのような文字列が50〜60個あり、このプロセスは数十億回必要です。

関数オブジェクトを辞書内に、関数自体に格納する:-

def func1():
   if dict.has_key('str1'):
        dict['str1'] = func1
   -- do something --

これと上記のどちらが良いですか。これはずっときれいに見えます。ただし、これらの関数は何度も呼び出されるため、has_key関数も何度も呼び出されることに注意してください。

ありがとう

4

7 に答える 7

16

辞書を選択してください。

辞書..。

  • ビルトイン
  • pythonicです
  • ボイラープレートコードが少なくて済みます
  • if-else線形O(n)複雑度と比較して、O(1)複雑度を持っています
  • 時期尚早の悲観化の罪を犯していない(それが大幅に効率の悪い方法であるとプロファイリングせずに信じる十分な理由がない)

最初に辞書を使用してソリューションを作成し、ソリューションがニーズに対して十分に高速であるかどうかを確認することをお勧めします。もしそうなら、素晴らしい、あなたは完了です。そうでない場合は、他の方法に対して時間を計ります。

次のような解決策を検討してください(None文字列が見つからない場合に返されます)。

func_dict = {}
func_dict['str1'] = fun1
func_dict['str2'] = fun2
...
def function_lookup(func_string):
    return func_dict.get(func_string)

次に、メインで、function_lookup(whatever_string_variable)関数のルックアップを試行するように記述します。function_lookupこれにより、が呼び出されるたびに辞書が再構築されるのを防ぎます。

于 2012-07-12T05:07:25.123 に答える
6

辞書はより高速になります。それはおよそO(1)ですが、ifステートメントのチェーンはO(n)です。実例を示すために、このスクリプト(make_test.py)は、いくつかのパフォーマンステストを実行するPythonスクリプトを出力します。

ifs = []
dict = []
for i in range(60):
    string = 'str%d' % i
    ifs.append('  %sif str == "%s": return %d' % ('el' if i else '', string, i))
    dict.append('"%s": %d' % (string, i))

print 'dict = {', ','.join(dict), '}'
print 'def with_dict(str):'
print '  return dict[str]'

print 'def with_if(str):'
print '\n'.join(ifs)

print '''
import timeit

def test_dict():
    for i in range(60):
        with_dict("str%d" % i)

def test_if():
    for i in range(60):
        with_if("str%d" %i)

print 'dict:', timeit.timeit(test_dict, number=10000)
print 'if:  ', timeit.timeit(test_if, number=10000)'''

のように実行すると、次のようpython make_test.py | pythonになります。

dict: 0.706176042557
if:   1.67383503914

つまり、ifバージョンはバージョンの2倍以上遅くなりますdict

于 2012-07-12T05:13:16.753 に答える
2

辞書は、Pythonの高度に調整された部分の1つです。それらはより読みやすいコードを生成します。ifループよりもパフォーマンスが優れているはずです。ただし、挿入やその他のオーバーヘッドを考慮すると、timeitモジュールを使用してパフォーマンスを確認することをお勧めします。

于 2012-07-12T05:07:46.930 に答える
2

技術的には、ハッシュ衝突のパフォーマンスに依存しますが、すべてのデータをハッシュに格納して取得する方が少し速いと思います。

いずれにせよ、どちらの方法でも違いはおそらく大きくはないでしょう。確かに、ハッシュテーブルソリューションはよりクリーンなので、それをお勧めします。

確実に知るための最良の方法は、両方のバージョンを作成し、それらを大量のデータでテストして、それらのパフォーマンスを測定することです。

于 2012-07-12T05:01:08.390 に答える
2

辞書の方がいいです。辞書はツリー/ハッシュマップに裏打ちされている必要があり、if-elseステートメント(ほぼ線形)よりも時間計算量が優れています。実際の実行時間が良くない場合でも、コードは辞書でよりクリーンになります。

于 2012-07-12T05:01:52.223 に答える
0

dictルックアップの平均時間計算量はO(1)です。最悪の場合はO(n)です。strキーのみを使用する辞書の最適化があります(ユースケース)。

if / elseラダーでのテストの順序自体が、入力の頻度に基づいて最適化できないと仮定すると(たとえば、60の可能性、そのうち2つは95%の確率で発生します)、一連のif/elseステートメントの複雑さO(n)です。

したがって、辞書を使用すると、パフォーマンスが向上し、コードの可読性も向上します。

于 2012-07-12T05:14:41.543 に答える
-1

どのソリューションがよりエレガントに見え、保守が容易です。

ほとんどのアプリケーションプログラミングでは、人間の時間と保守性を最適化することの方が、コンピューターの時間を最適化することよりも重要です。コンピュータの時間は安いです。人間の時間は高価です。

どちらのソリューションにも利点があります。

if / elifソリューションは、ネストされたif / elseのように、後で制御フローを追加する必要がある場合に、より柔軟性を提供する可能性があります。

データがyamlやデータベースなどのデータソースから直接取得されている場合は、明らかにdictソリューションの方が洗練されています。

于 2014-10-30T23:20:44.960 に答える