在蟒蛇,当使用的字符串连接与串替代躲开我。为字符串连接已经看到很大提高的性能,这是(变得更加)一个风格的决定,而不是一个实际的一个吗?

对于一个具体的例子,一个人应该如何处理的建设性Uri:

DOMAIN = 'http://stackoverflow.com'
QUESTIONS = '/questions'

def so_question_uri_sub(q_num):
    return "%s%s/%d" % (DOMAIN, QUESTIONS, q_num)

def so_question_uri_cat(q_num):
    return DOMAIN + QUESTIONS + '/' + str(q_num)

编辑:还有人建议,关于加入一串名单和使用名为替代。这些都是变异体上的中心主题,这是说,其方式是正确的方式做到这一点,其时间?谢谢你的反应!

有帮助吗?

解决方案

级联是(显著)更快根据我的机器。但在风格上,我愿意支付替代的价格,如果性能并不重要。好吧,如果我需要的格式,没有必要连问的问题...有没有办法只好用插/模板。

>>> import timeit
>>> def so_q_sub(n):
...  return "%s%s/%d" % (DOMAIN, QUESTIONS, n)
...
>>> so_q_sub(1000)
'http://stackoverflow.com/questions/1000'
>>> def so_q_cat(n):
...  return DOMAIN + QUESTIONS + '/' + str(n)
...
>>> so_q_cat(1000)
'http://stackoverflow.com/questions/1000'
>>> t1 = timeit.Timer('so_q_sub(1000)','from __main__ import so_q_sub')
>>> t2 = timeit.Timer('so_q_cat(1000)','from __main__ import so_q_cat')
>>> t1.timeit(number=10000000)
12.166618871951641
>>> t2.timeit(number=10000000)
5.7813972166853773
>>> t1.timeit(number=1)
1.103492206766532e-05
>>> t2.timeit(number=1)
8.5206360154188587e-06

>>> def so_q_tmp(n):
...  return "{d}{q}/{n}".format(d=DOMAIN,q=QUESTIONS,n=n)
...
>>> so_q_tmp(1000)
'http://stackoverflow.com/questions/1000'
>>> t3= timeit.Timer('so_q_tmp(1000)','from __main__ import so_q_tmp')
>>> t3.timeit(number=10000000)
14.564135316080637

>>> def so_q_join(n):
...  return ''.join([DOMAIN,QUESTIONS,'/',str(n)])
...
>>> so_q_join(1000)
'http://stackoverflow.com/questions/1000'
>>> t4= timeit.Timer('so_q_join(1000)','from __main__ import so_q_join')
>>> t4.timeit(number=10000000)
9.4431309007150048

其他提示

不要忘了名为取代:

def so_question_uri_namedsub(q_num):
    return "%(domain)s%(questions)s/%(q_num)d" % locals()

<强>警惕在循环连接字符串的<!/强>字符串连接的成本正比于结果的长度。循环导致你直接到N平方的土地。有些语言将优化级联到最近分配的字符串,但它是有风险的编译器计数来优化您的二次算法到线性。最好使用原语(join?),其采用串的完整列表,做一个单一的分配,以及连接它们都一气呵成。

“作为字符串连接已经看到了在性能方面有大提升...”

如果性能问题,这是很好的了解。

不过,我已经看到了性能问题从来没有回落到字符串操作。我已经通常得到在麻烦I / O,排序和O(名词 2 )操作是所述瓶颈。

到字符串操作的性能限制,我会坚持的东西是显而易见的。大多数情况下,这就是置换时,它的一条线或更小,当它是有意义级联,和一个模板工具(如真子)时,它的大。

你想要什么连接/插入以及如何你想要的格式,结果应驱动的决定。

  • 串插可以让你轻松地添加的格式。事实上,你的串插版本不会做同样的事情,因为你的串联的版本;它实际上增加了额外的斜线之前 q_num 参数。做同样的事情,你会写 return DOMAIN + QUESTIONS + "/" + str(q_num) 在这一范例。

  • 插使它更加容易以数字格式; "%d of %d (%2.2f%%)" % (current, total, total/current) 将少得多的可读的,在级联的形式。

  • 连接是有用的,当你不具有固定的项目数字符串ize.

此外,知道Python2.6引入了一个新版本的串的内插法,称为 串的模板:

def so_question_uri_template(q_num):
    return "{domain}/{questions}/{num}".format(domain=DOMAIN,
                                               questions=QUESTIONS,
                                               num=q_num)

串的模板将最终取代%插值,但这不会发生相当长一段时间,我想。

我只是测试的不同字符串连接/置换方法的速度好奇。关于这个问题的谷歌搜索把我带到这里。我想我会后我的测试结果,希望它可以帮助别人决定。

    import timeit
    def percent_():
            return "test %s, with number %s" % (1,2)

    def format_():
            return "test {}, with number {}".format(1,2)

    def format2_():
            return "test {1}, with number {0}".format(2,1)

    def concat_():
            return "test " + str(1) + ", with number " + str(2)

    def dotimers(func_list):
            # runs a single test for all functions in the list
            for func in func_list:
                    tmr = timeit.Timer(func)
                    res = tmr.timeit()
                    print "test " + func.func_name + ": " + str(res)

    def runtests(func_list, runs=5):
            # runs multiple tests for all functions in the list
            for i in range(runs):
                    print "----------- TEST #" + str(i + 1)
                    dotimers(func_list)

...运行runtests((percent_, format_, format2_, concat_), runs=5)后,我发现%方法大约快两倍,这些小串等。该concat方法总是最慢(勉强)。有切换在format()方法的位置时非常微小的差异,但切换位置总是比普通格式方法至少0.01慢。

测试结果的示例:

    test concat_()  : 0.62  (0.61 to 0.63)
    test format_()  : 0.56  (consistently 0.56)
    test format2_() : 0.58  (0.57 to 0.59)
    test percent_() : 0.34  (0.33 to 0.35)

我跑了这些,因为我使用的字符串连接在我的剧本,我想知道是什么费用。我跑了他们在不同的顺序,以确保没有被干扰,或得到更好的性能是第一个或最后。在一个侧面说明,我扔在一些较长的字符串发电机到像"%s" + ("a" * 1024)和定期CONCAT这些功能是一样快(1.1 VS 2.8)的使用format%方法近3倍。我想这取决于在弦上,和你正在努力实现。如果性能真的很重要,它可能是更好地尝试不同的东西,并对其进行测试。我倾向于选择超速可读性,除非速度成为一个问题,但是那只是我。 SO不喜欢我的复制/粘贴,我只好把8位的一切,使它看起来正确的。我通常使用4。

记住,风格决定的的实际决定,如果你打算保持或调试代码:-)有来自高德纳(可能是引述霍尔?)一句名言:“我们应该忘记小效率,说的时间的约97%:过早的优化是所有罪恶的根源“

只要你小心,不要(说)把一个O(n)的任务分解成一个O(N 2 )的任务,我会无论你找到最容易理解的去..

我使用替换的地方我可以。我只用串联如果我在说一个for循环建立一个字符串中。

实际上正确的事,在这种情况下(建筑路径)是使用os.path.join。不字符串连接或插

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top