2

Pythonリファレンスマニュアルによると:

文字列は、その文字に相当する数値 (組み込み関数 ord() の結果) を使用して、辞書式に比較されます。Unicode と 8 ビット文字列は、この動作で完全に相互運用可能です。

つまり、ハッシュはこの目的には使用されません。

ここで、等価性テスト中に内部的に Python が最初に 2 つの文字列の長さをチェックし、両方が同じ長さである場合は辞書式比較に進むと仮定しましょう (他のすべての比較でも同じことが行われると思います)。

そうだとすれば、次の 2 つの異なる比較では、なぜ異なる時間がかかるのでしょうか?

>>> str1 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge1"
>>> 
>>> str2 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge2"
>>> 
>>> def compare():
     t1 = time.time()
     for x in xrange(100000000):
         str1 == str2
     print time.time() - t1
 
>>> 
>>> compare()
13.001019001
>>> 
>>> str2 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge1"
>>> 
>>> compare()
7.41645097733

両方の比較str1で、 とstr2は同じ長さです。最初のものはどちらも最後の文字だけが異なり、2 番目のものは何も異なりません。

PS: 長い文字列と大きな反復を使用して、違いを認識できるようにしました。

4

4 に答える 4

1

多くの言語と同様に、Python には文字列リテラルのプールがいくつかあります。2 番目のケースでは、実際には両方の文字列が同じオブジェクトであるため、実際の値ではなく参照によって比較されます。

参照ベースの言語における典型的な文字列比較関数:

if (ref(a) == ref(b)) return true;
if (len(a) != len(b)) return false;
return compare_actual_data(a, b);
于 2012-09-16T14:42:22.617 に答える
1

他の回答が推測しているように、文字列が同一である場合、比較は実際に短絡されています。これは、同じ内容の文字列リテラルの場合です。

于 2012-09-16T14:47:31.043 に答える
1

2 番目のケースでは、2 つの文字列は実際には同じ ID を持つ同じオブジェクトです。

str1 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge1"
str2 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge2"

def compare():
    t1 = time.time()
    for x in xrange(100000000):
        str1 == str2
    print time.time() - t1


print "%d, %d" % (id(str1), id(str2))
compare()

str2 = "foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge_foo_bar_cruft_kludge1"

print "%d, %d" % (id(str1), id(str2))
compare()

2 番目のケースでは、ID が同一であるため、Python インタープリターは文字列全体をバイト単位で比較する必要はありません。

于 2012-09-16T14:49:49.563 に答える
0

2つの文字列が「インターン」されている場合、それらはポインタ比較によって比較できます。たぶんこの場合、バイトコードジェネレータは文字列が定数であることに気づき、それらをインターンしますか?

小さいタイミングが弦の長さにほとんど依存しない(または独立しない)ことを示すことで、これを実証(または反証)することができます。

そして確かに、私はこれらの結果を得る:

$ ./test.py 
17.4877259731
8.61179995537
$ ./test_halflengthstrings.py 
12.6504788399
8.58732700348
于 2012-09-16T14:41:14.317 に答える