为什么 repr(int) 比 str(int) 快? [英] Why is repr(int) faster than str(int)?

查看:49
本文介绍了为什么 repr(int) 比 str(int) 快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么 repr(int)str(int) 快.使用以下代码片段:

I am wondering why repr(int) is faster than str(int). With the following code snippet:

ROUNDS = 10000

def concat_strings_str():
    return ''.join(map(str, range(ROUNDS)))

def concat_strings_repr():
    return ''.join(map(repr, range(ROUNDS)))

%timeit concat_strings_str()
%timeit concat_strings_repr()

我得到了这些时间(python 3.5.2,但与 2.7.12 的结果非常相似):

I get these timings (python 3.5.2, but very similar results with 2.7.12):

 1.9 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
 1.38 ms ± 9.07 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

如果我在正确的道路上,同样的功能long_to_decimal_string 在幕后被调用.

If I'm on the right path, the same function long_to_decimal_string is getting called below the hood.

是我做错了什么还是我遗漏了什么?

Did I get something wrong or what else is going on that I am missing?

更新:这可能与 int__repr____str__ 方法无关,但与 repr()str(),因为 int.__str__int.__repr__ 实际上相当快:

update: This probably has nothing to with int's __repr__ or __str__ methods but with the differences between repr() and str(), as int.__str__ and int.__repr__ are in fact comparably fast:

def concat_strings_str():
    return ''.join([one.__str__() for one in range(ROUNDS)])

def concat_strings_repr():
    return ''.join([one.__repr__() for one in range(ROUNDS)])

%timeit concat_strings_str()
%timeit concat_strings_repr()

结果:

2.02 ms ± 24.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.05 ms ± 7.07 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

推荐答案

因为使用 str(obj) 必须先经过 type.__call__ 然后 str.__new__(创建一个新字符串) 然后 PyObject_Str(制作一个字符串对象之外),它调用 int.__str__最后,使用你链接的函数.

Because using str(obj) must first go through type.__call__ then str.__new__ (create a new string) then PyObject_Str (make a string out of the object) which invokes int.__str__ and, finally, uses the function you linked.

repr(obj),对应builtin_repr,直接调用PyObject_Repr(获取对象代表) 然后调用 int.__repr__ 使用与int.__相同的函数.代码>.

repr(obj), which corresponds to builtin_repr, directly calls PyObject_Repr (get the object repr) which then calls int.__repr__ which uses the same function as int.__str__.

此外,它们通过call_function(处理CALL_FUNCTION 操作码(为调用生成)略有不同.

Additionally, the path they take through call_function (the function that handles the CALL_FUNCTION opcode that's generated for calls) is slightly different.

来自 GitHub (CPython 3.7) 上的 master 分支:

From the master branch on GitHub (CPython 3.7):

  • str goes through _PyObject_FastCallKeywords (which is the one that calls type.__call__). Apart from performing more checks, this also needs to create a tuple to hold the positional arguments (see _PyStack_AsTuple).
  • repr goes through _PyCFunction_FastCallKeywords which calls _PyMethodDef_RawFastCallKeywords. repr is also lucky because, since it only accepts a single argument (the switch leads it to the METH_0 case in _PyMethodDef_RawFastCallKeywords) there's no need to create a tuple, just indexing of the args.

正如您的更新所述,这与 int.__repr__int.__str__ 无关,毕竟它们是相同的功能;这完全取决于 reprstr 如何到达它们.str 只需要更努力一点.

As your update states, this isn't about int.__repr__ vs int.__str__, they are the same function after all; it's all about how repr and str reach them. str just needs to work a bit harder.

这篇关于为什么 repr(int) 比 str(int) 快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆