1. ホーム
  2. python

[解決済み] Python インタープリタにとってバックティックは何を意味するのか: `num`

2023-03-02 05:37:24

質問

私はリスト内包で遊んでいて、他のサイトでこの小さなスニペットに出会いました。

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秒かかります。

どちらも同じ結果を出しますが、一方はずっと遅いです。どうなっているのでしょうか?

EDITです。 奇しくも... repr() よりもわずかに遅い結果を与えます。 `num` . 2.99s vs 2.43sです。Python 2.6を使用(3.0はまだ試していません)。

どのように解決するのですか?

バックティックは、非推奨のエイリアスで repr() . この構文は Python 3.0 で削除されましたので、もう使わないでください。

を使うよりバックティックを使う方が速いようです。 repr(num) または num.__repr__() バージョン 2.x では、グローバル名前空間での追加の辞書検索が必要なためだと思います ( 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 は、グローバルなルックアップで repr , f2 に対する属性ルックアップ __repr__ の属性検索を行うのに対し、バックチッ ク演算子は別のオペコードで実装されています。辞書引きのためのオーバーヘッドがないので ( LOAD_GLOBAL / LOAD_ATTR ) や関数呼び出し ( CALL_FUNCTION ) の場合、バックチックの方が速いです。

Pythonの人たちは、低レベルの操作を別個に持つことが repr() のために別の低レベル操作を持つことは価値がなく、両方の repr() とバックティックの両方を持つことは、この原則に反しています。

1つの、そしてできれば1つだけの、明白な方法があるはずです。

というわけで、この機能はPython 3.0で削除されました。