リスト内包表記をいじっていますが、別のサイトでこの小さなスニペットに出会いました。
_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秒かかります。
どちらも同じ結果になりますが、1つはかなり遅いです。ここで何が起こっていますか?
編集:奇妙な... repr()
は_`num`
_よりも少し遅い結果を与えます。 2.99秒と2.43秒。 Python 2.6(まだ3.0を試していません)を使用しています。
バックティックは、repr()
の廃止されたエイリアスです。これ以上使用しないでください。構文はPython 3.0で削除されました。
バージョン2.xでrepr(num)
または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
には、repr
、f2
のグローバルルックアップ、__repr__
の属性ルックアップが含まれますが、バックティック演算子は別のオペコードに実装されます。辞書検索(LOAD_GLOBAL
/LOAD_ATTR
)や関数呼び出し(CALL_FUNCTION
)のオーバーヘッドがないため、バックティックは高速です。
Python人々は、repr()
に対して個別の低レベル操作を行うことは価値がないと判断し、repr()
とバックティックの両方を持つことは原則に違反する
「1つ-そしてできれば1つだけ-それを行う明白な方法があるべきです」
そのため、この機能はPython 3.0で削除されました。
バックティッククォートは一般に役に立たず、Python 3。
それが価値があるものについては、これ:
''.join(map(repr, xrange(10000000)))
私のバックティックバージョンよりもわずかに高速です。しかし、これを心配するのはおそらく時期尚早な最適化です。
私の推測では、num
は__str__()
メソッドを定義していないので、str()
は___repr__
_の2回目の検索を行う必要があります。
バックティックは___repr__
_を直接探します。それが当てはまる場合、バックティックの代わりにrepr()
を使用しても同じ結果が得られます。