标签归档:string-concatenation

在python中连接字符串和整数

问题:在python中连接字符串和整数

用python说你有

s = "string"
i = 0
print s+i

会给你错误,所以你写

print s+str(i) 

不会出错。

我认为这是处理int和字符串连接的笨拙方式。甚至Java也不需要显式转换为String来进行这种连接。有没有更好的方法来进行这种串联,即在Python中无需显式转换?

In python say you have

s = "string"
i = 0
print s+i

will give you error so you write

print s+str(i) 

to not get error.

I think this is quite a clumsy way to handle int and string concatenation. Even Java does not need explicit casting to String to do this sort of concatenation. Is there a better way to do this sort of concatenation i.e without explicit casting in Python?


回答 0

现代字符串格式:

"{} and {}".format("string", 1)

Modern string formatting:

"{} and {}".format("string", 1)

回答 1

没有字符串格式:

>> print 'Foo',0
Foo 0

No string formatting:

>> print 'Foo',0
Foo 0

回答 2

使用新样式.format()方法(默认使用.format()提供)进行字符串格式化:

 '{}{}'.format(s, i)

或更旧的,但“仍然存在”,- %格式化:

 '%s%d' %(s, i)

在以上两个示例中,串联的两个项目之间没有空格。如果需要空间,可以简单地将其添加到格式字符串中。

这些提供了 如何串联项目,它们之间的空间等很多控制和灵活性。有关的详细信息格式规范的请参见此

String formatting, using the new-style .format() method (with the defaults .format() provides):

 '{}{}'.format(s, i)

Or the older, but “still sticking around”, %-formatting:

 '%s%d' %(s, i)

In both examples above there’s no space between the two items concatenated. If space is needed, it can simply be added in the format strings.

These provide a lot of control and flexibility about how to concatenate items, the space between them etc. For details about format specifications see this.


回答 3

Python是一种有趣的语言,尽管通常有一种(或两种)“显而易见”的方式来完成任何给定的任务,但灵活性仍然存在。

s = "string"
i = 0

print (s + repr(i))

上面的代码段使用Python3语法编写,但始终允许打印后的括号(可选),直到版本3强制使用为止。

希望这可以帮助。

凯特琳

Python is an interesting language in that while there is usually one (or two) “obvious” ways to accomplish any given task, flexibility still exists.

s = "string"
i = 0

print (s + repr(i))

The above code snippet is written in Python3 syntax but the parentheses after print were always allowed (optional) until version 3 made them mandatory.

Hope this helps.

Caitlin


回答 4

format()方法可用于连接字符串和整数

print(s+"{}".format(i))

format() method can be used to concatenate string and integer

print(s+"{}".format(i))

回答 5

如果您只想打印哟,可以这样做:

print(s , i)

if you only want to print yo can do this:

print(s , i)

回答 6

在python 3.6及更高版本中,您可以像这样格式化它:

new_string = f'{s} {i}'
print(new_string)

要不就:

print(f'{s} {i}')

in python 3.6 and newer, you can format it just like this:

new_string = f'{s} {i}'
print(new_string)

or just:

print(f'{s} {i}')

有什么理由不使用’+’连接两个字符串吗?

问题:有什么理由不使用’+’连接两个字符串吗?

Python中常见的反模式是+在循环中使用串联字符串序列。这很不好,因为Python解释器必须为每次迭代创建一个新的字符串对象,并且最终要花费二次时间。(在某些情况下,最新版本的CPython显然可以优化此功能,但其他实现则不能,因此建议程序员不要依赖此功能。)''.join是执行此操作的正确方法。

但是,我听说它说过(包括Stack Overflow上的内容),您永远都不要将它+用于字符串连接,而应该始终使用''.join或格式字符串。我不明白为什么只连接两个字符串会出现这种情况。如果我的理解是正确的,则不应该花费二次时间,而且我认为a + b''.join((a, b))或更加简洁易读'%s%s' % (a, b)

+串联两个字符串是否是一种好习惯?还是有我不知道的问题?

A common antipattern in Python is to concatenate a sequence of strings using + in a loop. This is bad because the Python interpreter has to create a new string object for each iteration, and it ends up taking quadratic time. (Recent versions of CPython can apparently optimize this in some cases, but other implementations can’t, so programmers are discouraged from relying on this.) ''.join is the right way to do this.

However, I’ve heard it said (including here on Stack Overflow) that you should never, ever use + for string concatenation, but instead always use ''.join or a format string. I don’t understand why this is the case if you’re only concatenating two strings. If my understanding is correct, it shouldn’t take quadratic time, and I think a + b is cleaner and more readable than either ''.join((a, b)) or '%s%s' % (a, b).

Is it good practice to use + to concatenate two strings? Or is there a problem I’m not aware of?


回答 0

两个字符串与连接在一起没有错+。确实,它比容易阅读''.join([a, b])

您是对的,尽管用2个以上的字符串进行连接+是O(n ^ 2)操作(与相比,O(n)join)因此效率低下。但是,这与使用循环无关。偶数a + b + c + ...为O(n ^ 2),原因是每个串联产生一个新的字符串。

CPython2.4及更高版本试图缓解这种情况,但是join在连接两个以上的字符串时仍然建议使用。

There is nothing wrong in concatenating two strings with +. Indeed it’s easier to read than ''.join([a, b]).

You are right though that concatenating more than 2 strings with + is an O(n^2) operation (compared to O(n) for join) and thus becomes inefficient. However this has not to do with using a loop. Even a + b + c + ... is O(n^2), the reason being that each concatenation produces a new string.

CPython2.4 and above try to mitigate that, but it’s still advisable to use join when concatenating more than 2 strings.


回答 1

加号运算符是连接两个 Python字符串的完美解决方案。但是,如果您继续添加两个以上的字符串(n> 25),则可能需要考虑其他问题。

''.join([a, b, c]) 技巧是性能优化。

Plus operator is perfectly fine solution to concatenate two Python strings. But if you keep adding more than two strings (n > 25) , you might want to think something else.

''.join([a, b, c]) trick is a performance optimization.


回答 2

假设永远不要使用+进行字符串连接,而始终使用”.join可能是一个神话。的确,使用+会创建不必要的不​​可变字符串对象的临时副本,但另一个经常引用的事实是,join在循环中调用通常会增加的开销function call。让我们举个例子。

创建两个列表,一个来自链接的SO问题,另一个列表更大

>>> myl1 = ['A','B','C','D','E','F']
>>> myl2=[chr(random.randint(65,90)) for i in range(0,10000)]

让我们创建两个函数,UseJoinUsePlus分别使用join+功能。

>>> def UsePlus():
    return [myl[i] + myl[i + 1] for i in range(0,len(myl), 2)]

>>> def UseJoin():
    [''.join((myl[i],myl[i + 1])) for i in range(0,len(myl), 2)]

让timeit与第一个列表一起运行

>>> myl=myl1
>>> t1=timeit.Timer("UsePlus()","from __main__ import UsePlus")
>>> t2=timeit.Timer("UseJoin()","from __main__ import UseJoin")
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
2.48 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
2.61 usec/pass
>>> 

它们具有几乎相同的运行时。

让我们使用cProfile

>>> myl=myl2
>>> cProfile.run("UsePlus()")
         5 function calls in 0.001 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001    0.001    0.001 <pyshell#1376>:1(UsePlus)
        1    0.000    0.000    0.001    0.001 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {range}


>>> cProfile.run("UseJoin()")
         5005 function calls in 0.029 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.015    0.015    0.029    0.029 <pyshell#1388>:1(UseJoin)
        1    0.000    0.000    0.029    0.029 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     5000    0.014    0.000    0.014    0.000 {method 'join' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {range}

而且看起来使用Join会导致不必要的函数调用,这可能会增加开销。

现在回到问题。在所有情况下都应该不鼓励使用+over join吗?

我相信不,应该考虑

  1. 所讨论字符串的长度
  2. 串联操作数。

在开发中过早地进行优化是不明智的。

The assumption that one should never, ever use + for string concatenation, but instead always use ”.join may be a myth. It is true that using + creates unnecessary temporary copies of immutable string object but the other not oft quoted fact is that calling join in a loop would generally add the overhead of function call. Lets take your example.

Create two lists, one from the linked SO question and another a bigger fabricated

>>> myl1 = ['A','B','C','D','E','F']
>>> myl2=[chr(random.randint(65,90)) for i in range(0,10000)]

Lets create two functions, UseJoin and UsePlus to use the respective join and + functionality.

>>> def UsePlus():
    return [myl[i] + myl[i + 1] for i in range(0,len(myl), 2)]

>>> def UseJoin():
    [''.join((myl[i],myl[i + 1])) for i in range(0,len(myl), 2)]

Lets run timeit with the first list

>>> myl=myl1
>>> t1=timeit.Timer("UsePlus()","from __main__ import UsePlus")
>>> t2=timeit.Timer("UseJoin()","from __main__ import UseJoin")
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
2.48 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
2.61 usec/pass
>>> 

They have almost the same runtime.

Lets use cProfile

>>> myl=myl2
>>> cProfile.run("UsePlus()")
         5 function calls in 0.001 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001    0.001    0.001 <pyshell#1376>:1(UsePlus)
        1    0.000    0.000    0.001    0.001 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {range}


>>> cProfile.run("UseJoin()")
         5005 function calls in 0.029 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.015    0.015    0.029    0.029 <pyshell#1388>:1(UseJoin)
        1    0.000    0.000    0.029    0.029 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     5000    0.014    0.000    0.014    0.000 {method 'join' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {range}

And it looks that using Join, results in unnecessary function calls which could add to the overhead.

Now coming back to the question. Should one discourage the use of + over join in all cases?

I believe no, things should be taken into consideration

  1. Length of the String in Question
  2. No of Concatenation Operation.

And off-course in a development pre-mature optimization is evil.


回答 3

与多个人一起工作时,有时很难确切知道正在发生什么。使用格式字符串而不是连接可以避免对我们造成无数次特定烦恼:

说,一个函数需要一个参数,然后编写它以获取字符串:

In [1]: def foo(zeta):
   ...:     print 'bar: ' + zeta

In [2]: foo('bang')
bar: bang

因此,在整个代码中可能经常使用此功能。您的同事可能确切知道它的功能,但不一定完全了解内部功能,并且可能不知道该函数需要一个字符串。因此,他们最终可能会这样:

In [3]: foo(23)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

/home/izkata/<ipython console> in foo(zeta)

TypeError: cannot concatenate 'str' and 'int' objects

如果您只使用格式字符串,将没有问题:

In [1]: def foo(zeta):
   ...:     print 'bar: %s' % zeta
   ...:     
   ...:     

In [2]: foo('bang')
bar: bang

In [3]: foo(23)
bar: 23

对于所有定义了的对象,__str__也可以传入:

In [1]: from datetime import date

In [2]: zeta = date(2012, 4, 15)

In [3]: print 'bar: ' + zeta
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

TypeError: cannot concatenate 'str' and 'datetime.date' objects

In [4]: print 'bar: %s' % zeta
bar: 2012-04-15

所以可以:如果您可以使用格式字符串,充分利用Python所提供的功能。

When working with multiple people, it’s sometimes difficult to know exactly what’s happening. Using a format string instead of concatenation can avoid one particular annoyance that’s happened a whole ton of times to us:

Say, a function requires an argument, and you write it expecting to get a string:

In [1]: def foo(zeta):
   ...:     print 'bar: ' + zeta

In [2]: foo('bang')
bar: bang

So, this function may be used pretty often throughout the code. Your coworkers may know exactly what it does, but not necessarily be fully up-to-speed on the internals, and may not know that the function expects a string. And so they may end up with this:

In [3]: foo(23)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

/home/izkata/<ipython console> in foo(zeta)

TypeError: cannot concatenate 'str' and 'int' objects

There would be no problem if you just used a format string:

In [1]: def foo(zeta):
   ...:     print 'bar: %s' % zeta
   ...:     
   ...:     

In [2]: foo('bang')
bar: bang

In [3]: foo(23)
bar: 23

The same is true for all types of objects that define __str__, which may be passed in as well:

In [1]: from datetime import date

In [2]: zeta = date(2012, 4, 15)

In [3]: print 'bar: ' + zeta
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/izkata/<ipython console> in <module>()

TypeError: cannot concatenate 'str' and 'datetime.date' objects

In [4]: print 'bar: %s' % zeta
bar: 2012-04-15

So yes: If you can use a format string do it and take advantage of what Python has to offer.


回答 4

我做了一个快速测试:

import sys

str = e = "a xxxxxxxxxx very xxxxxxxxxx long xxxxxxxxxx string xxxxxxxxxx\n"

for i in range(int(sys.argv[1])):
    str = str + e

并定时:

mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  8000000
8000000 times

real    0m2.165s
user    0m1.620s
sys     0m0.540s
mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  16000000
16000000 times

real    0m4.360s
user    0m3.480s
sys     0m0.870s

显然有针对此a = a + b情况的优化。它没有表现出人们可能会怀疑的O(n ^ 2)时间。

因此,至少在性能方面,使用+还不错。

I have done a quick test:

import sys

str = e = "a xxxxxxxxxx very xxxxxxxxxx long xxxxxxxxxx string xxxxxxxxxx\n"

for i in range(int(sys.argv[1])):
    str = str + e

and timed it:

mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  8000000
8000000 times

real    0m2.165s
user    0m1.620s
sys     0m0.540s
mslade@mickpc:/binks/micks/ruby/tests$ time python /binks/micks/junk/strings.py  16000000
16000000 times

real    0m4.360s
user    0m3.480s
sys     0m0.870s

There is apparently an optimisation for the a = a + b case. It does not exhibit O(n^2) time as one might suspect.

So at least in terms of performance, using + is fine.


回答 5

根据Python文档,使用str.join()将为您提供各种Python实现的性能一致性。尽管CPython优化了s = s + t的二次行为,但其他Python实现可能没有。

CPython实现细节:如果s和t都是字符串,则某些Python实现(例如CPython)通常可以对s = s + t或s + = t形式的赋值执行就地优化。如果适用,此优化将使二次运行的可能性大大降低。此优化取决于版本和实现。对于性能敏感的代码,最好使用str.join()方法,以确保各个版本和实现之间一致的线性串联性能。

Python文档中的序列类型(请参见脚注[6])

According to Python docs, using str.join() will give you performance consistence across various implementations of Python. Although CPython optimizes away the quadratic behavior of s = s + t, other Python implementations may not.

CPython implementation detail: If s and t are both strings, some Python implementations such as CPython can usually perform an in-place optimization for assignments of the form s = s + t or s += t. When applicable, this optimization makes quadratic run-time much less likely. This optimization is both version and implementation dependent. For performance sensitive code, it is preferable to use the str.join() method which assures consistent linear concatenation performance across versions and implementations.

Sequence Types in Python docs (see the foot note [6])


回答 6

我在python 3.8中使用以下内容

string4 = f'{string1}{string2}{string3}'

I use the following with python 3.8

string4 = f'{string1}{string2}{string3}'

回答 7

”.join([a,b])+更好。

因为应该以不损害Python其他实现(PyPy,Jython,IronPython,Cython,Psyco等)的方式编写代码

形式a + = b或a = a + b即使在CPython中也很脆弱,并且在不使用 引用计数的 实现中根本不存在(引用计数是一种存储引用,指针或对a的句柄的技术资源,例如对象,内存块,磁盘空间或其他资源

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

”.join([a, b]) is better solution than +.

Because Code should be written in a way that does not disadvantage other implementations of Python (PyPy, Jython, IronPython, Cython, Psyco, and such)

form a += b or a = a + b is fragile even in CPython and isn’t present at all in implementations that don’t use refcounting (reference counting is a technique of storing the number of references, pointers, or handles to a resource such as an object, block of memory, disk space or other resource)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


Python中的字符串串联与字符串替换

问题:Python中的字符串串联与字符串替换

在Python中,使用字符串连接与字符串替换的时间和地点使我难以理解。由于字符串连接的性能有了很大提高,这(成为更多)是一种风格上的决定,而不是一种实际的决定吗?

举一个具体的例子,如何处理灵活的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)

编辑:也有关于加入字符串列表和使用命名替换的建议。这些是中心主题的变体,即在什么时候做正确的方法?感谢您的回复!

In Python, the where and when of using string concatenation versus string substitution eludes me. As the string concatenation has seen large boosts in performance, is this (becoming more) a stylistic decision rather than a practical one?

For a concrete example, how should one handle construction of flexible URIs:

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)

Edit: There have also been suggestions about joining a list of strings and for using named substitution. These are variants on the central theme, which is, which way is the Right Way to do it at which time? Thanks for the responses!


回答 0

根据我的机器,连接的速度(明显)更快。但从风格上讲,如果性能不是很关键,我愿意付出替代的代价。好吧,如果我需要格式化,就不用问这个问题了……别无选择,只能使用插值/模板化。

>>> 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

Concatenation is (significantly) faster according to my machine. But stylistically, I’m willing to pay the price of substitution if performance is not critical. Well, and if I need formatting, there’s no need to even ask the question… there’s no option but to use interpolation/templating.

>>> 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

回答 1

不要忘记命名替换:

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

Don’t forget about named substitution:

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

回答 2

小心将字符串串联在一起! 字符串连接的代价与结果的长度成正比。循环使您直接进入N平方的区域。某些语言会优化串联到最近分配的字符串,但是依靠编译器将二次算法优化到线性优化是有风险的。最好使用原语(join?),该原语接收整个字符串列表,进行一次分配,然后一次性将它们全部串联起来。

Be wary of concatenating strings in a loop! The cost of string concatenation is proportional to the length of the result. Looping leads you straight to the land of N-squared. Some languages will optimize concatenation to the most recently allocated string, but it’s risky to count on the compiler to optimize your quadratic algorithm down to linear. Best to use the primitive (join?) that takes an entire list of strings, does a single allocation, and concatenates them all in one go.


回答 3

“由于字符串串联已经大大提高了性能……”

如果性能很重要,这是个好消息。

但是,我所见过的性能问题从未归结为字符串操作。我通常遇到I / O,排序和O(n 2)操作成为瓶颈的麻烦。

在字符串操作成为性能限制因素之前,我将坚持显而易见的事情。通常,当一行或更少行时,这是替换;当有意义时,则是串联;当它很大时,则是模板工具(例如Mako)。

“As the string concatenation has seen large boosts in performance…”

If performance matters, this is good to know.

However, performance problems I’ve seen have never come down to string operations. I’ve generally gotten in trouble with I/O, sorting and O(n2) operations being the bottlenecks.

Until string operations are the performance limiters, I’ll stick with things that are obvious. Mostly, that’s substitution when it’s one line or less, concatenation when it makes sense, and a template tool (like Mako) when it’s large.


回答 4

您要串联/插值的内容以及结果格式的格式应该会影响您的决策。

  • 字符串插值使您可以轻松添加格式。实际上,您的字符串插值版本与连接版本的功能不同。实际上,它会在q_num参数之前添加一个额外的正斜杠。要执行相同的操作,您将必须return DOMAIN + QUESTIONS + "/" + str(q_num)在该示例中编写。

  • 插值使设置数字格式更加容易;"%d of %d (%2.2f%%)" % (current, total, total/current)串联形式的可读性将大大降低。

  • 当您没有固定数量的项目要进行字符串化时,串联很有用。

另外,请知道Python 2.6引入了新版本的字符串插值,称为字符串模板

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

字符串模板将最终取代%插值,但是我认为这不会出现很长时间。

What you want to concatenate/interpolate and how you want to format the result should drive your decision.

  • String interpolation allows you to easily add formatting. In fact, your string interpolation version doesn’t do the same thing as your concatenation version; it actually adds an extra forward slash before the q_num parameter. To do the same thing, you would have to write return DOMAIN + QUESTIONS + "/" + str(q_num) in that example.

  • Interpolation makes it easier to format numerics; "%d of %d (%2.2f%%)" % (current, total, total/current) would be much less readable in concatenation form.

  • Concatenation is useful when you don’t have a fixed number of items to string-ize.

Also, know that Python 2.6 introduces a new version of string interpolation, called string templating:

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

String templating is slated to eventually replace %-interpolation, but that won’t happen for quite a while, I think.


回答 5

我只是出于好奇而测试了不同的字符串连接/替换方法的速度。谷歌搜索该主题将我带到这里。我以为我会发布测试结果,希望它可以帮助某人做出决定。

    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的速度几乎是使用formatand %方法的三倍(1.1 vs 2.8)。我想这取决于字符串以及您要实现的目标。如果性能确实很重要,那么尝试不同的东西并进行测试可能会更好。除非速度成为问题,否则我倾向于选择可读性而不是速度,但这就是我。所以不喜欢我的复制/粘贴,我必须在所有内容上放置8个空格以使其看起来正确。我通常使用4。

I was just testing the speed of different string concatenation/substitution methods out of curiosity. A google search on the subject brought me here. I thought I would post my test results in the hope that it might help someone decide.

    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)

…After running runtests((percent_, format_, format2_, concat_), runs=5), I found that the % method was about twice as fast as the others on these small strings. The concat method was always the slowest (barely). There were very tiny differences when switching the positions in the format() method, but switching positions was always at least .01 slower than the regular format method.

Sample of test results:

    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)

I ran these because I do use string concatenation in my scripts, and I was wondering what the cost was. I ran them in different orders to make sure nothing was interfering, or getting better performance being first or last. On a side note, I threw in some longer string generators into those functions like "%s" + ("a" * 1024) and regular concat was almost 3 times as fast (1.1 vs 2.8) as using the format and % methods. I guess it depends on the strings, and what you are trying to achieve. If performance really matters, it might be better to try different things and test them. I tend to choose readability over speed, unless speed becomes a problem, but thats just me. SO didn’t like my copy/paste, i had to put 8 spaces on everything to make it look right. I usually use 4.


回答 6

请记住,如果您打算维护或调试代码,则风格决定实际的决定:-) Knuth有句著名的名言(可能引述Hoare?):“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源。”

只要您小心谨慎,不要(例如)将O(n)任务转换为O(n 2)任务,无论您发现最容易理解的是什么,我都会选择。

Remember, stylistic decisions are practical decisions, if you ever plan on maintaining or debugging your code 🙂 There’s a famous quote from Knuth (possibly quoting Hoare?): “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.”

As long as you’re careful not to (say) turn a O(n) task into an O(n2) task, I would go with whichever you find easiest to understand..


回答 7

我会尽一切可能使用替代。如果要在for循环中构建字符串,则仅使用串联。

I use substitution wherever I can. I only use concatenation if I’m building a string up in say a for-loop.


回答 8

实际上,在这种情况下(构建路径),正确的做法是使用os.path.join。不是字符串串联或插值

Actually the correct thing to do, in this case (building paths) is to use os.path.join. Not string concatenation or interpolation