92

私はリスト内包表記をいじっていて、別のサイトでこの小さなスニペットに出くわしました:

return ''.join([`num` for num in xrange(loop_count)])

`num`ビットが機能を壊していることに気付く前に、(入力して)機能を複製しようと数分費やしました。

これらの文字でステートメントを囲むことは何をしますか? 私が見ることができるものから、それは str(num) と同等です。しかし、私がそれを計ったとき:

return ''.join([str(num) for num in xrange(10000000)])

4.09 秒かかります。

return ''.join([`num` for num in xrange(10000000)])

2.43秒かかります。

どちらも同じ結果が得られますが、一方はかなり遅くなります。ここで何が起こっているのですか?

編集:奇妙なことに...repr()よりもわずかに遅い結果が得られます`num`。2.99 秒対 2.43 秒。Python 2.6 を使用しています (3.0 はまだ試していません)。

4

3 に答える 3

128

バッククォートは の非推奨のエイリアスですrepr()。もう使用しないでください。この構文は Python 3.0 で削除されました。

バッククォートを使用すると、バージョン 2.x のrepr(num)orを使用するよりも高速になるようです。これは、グローバル名前空間 ( の場合) またはオブジェクトの名前空間 ( の場合) で、それぞれnum.__repr__()追加の辞書検索が必要なためだと思います。repr__repr__


モジュールを使用するとdis、私の仮定が証明されます。

def f1(a):
    return repr(a)

def f2(a):
    return a.__repr__()

def f3(a):
    return `a`

分解ショー:

>>> import dis
>>> dis.dis(f1)
  3           0 LOAD_GLOBAL              0 (repr)
              3 LOAD_FAST                0 (a)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE
>>> dis.dis(f2)
  6           0 LOAD_FAST                0 (a)
              3 LOAD_ATTR                0 (__repr__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE        
>>> dis.dis(f3)
  9           0 LOAD_FAST                0 (a)
              3 UNARY_CONVERT       
              4 RETURN_VALUE   

f1には、 のグローバル ルックアップreprf2の属性ルックアップが含まれます__repr__が、バックティック演算子は別のオペコードで実装されます。辞書検索 ( LOAD_GLOBAL/ LOAD_ATTR) や関数呼び出し ( CALL_FUNCTION) のオーバーヘッドがないため、バッククォートの方が高速です。

repr()Python の人々は、別の低レベルの操作を行うことは価値がないと判断したと思います。repr()と バッククォートの両方を使用することは原則に違反しています。

「それを行うための明白な方法が1つ、できれば1つだけあるはずです」

そのため、この機能は Python 3.0 で削除されました。

于 2009-11-04T11:03:58.820 に答える
10

バッククォートは一般的に役に立たず、Python 3 ではなくなりました。

価値があるのは、次のとおりです。

''.join(map(repr, xrange(10000000)))

私にとっては、バックティックバージョンよりもわずかに高速です。しかし、これについて心配するのは、おそらく時期尚早の最適化です。

于 2009-11-04T11:32:57.210 に答える
1

私の推測では、それはnumメソッドを定義していない__str__()のでstr()、2 番目のルックアップを行う必要があります__repr__

バッククォートは を直接探します__repr__。そうであればrepr()、バッククォートの代わりに使用しても同じ結果が得られます。

于 2009-11-04T11:05:22.923 に答える