-2

In this SO post, https://softwareengineering.stackexchange.com/questions/304445/why-is-s-better-than-for-concatenation, it is said that %s is better than +. but my tests show the opposite.

import string
import random

R = 10

def doit1():
    x =""
    for _ in range(R):
        x += random.choice(string.letters)


def doit2():
    y = ""
    for _ in range(R):
        y = "%s%s" % (y, random.choice(string.letters))


if __name__ == '__main__':
    import timeit
    print(timeit.timeit("doit1()", setup="from __main__ import doit1"))
    print(timeit.timeit("doit2()", setup="from __main__ import doit2"))

is giving me the below output:

➜  Documents python3.5 string_test.py
30.200247984997986
33.85921495900038

Seems like they are almost the same. Am I missing something here?

Community
  • 1
  • 1
joydeep bhattacharjee
  • 1,249
  • 4
  • 16
  • 42
  • 1
    I imagine this preference is mostly based on *readability* and not so much on performance, which btw depends on the runtime and other factors as well. – superuser0 Dec 29 '16 at 09:58
  • All user right for vote down. Timing comparator function always work with static variables. `y = "%s%s" % (y, random.choice(string.letters))` it's a joke ? – dsgdfg Dec 29 '16 at 11:02
  • Another point : `x += random.choice(string.letters)` where is all index ? – dsgdfg Dec 29 '16 at 11:18

5 Answers5

2

For 3.6 f-string are much faster:

enter image description here (required time to format, less is better)

Source and details: https://cito.github.io/blog/f-strings/

Eugene Lisitsky
  • 12,113
  • 5
  • 38
  • 59
1

In your case, string formatting is not very useful, and both variants are not good python. For list concatenation use .join:

def doit3():
    result = []
    for _ in range(R):
        result.append(random.choice(string.letters))
    return ''.join(result)
Daniel
  • 42,087
  • 4
  • 55
  • 81
0

Concatenation is faster than formatting but it is less maintainable and readable. I found a similar question: Python string formatting: % vs concatenation

Community
  • 1
  • 1
Andreas Rau
  • 338
  • 2
  • 11
0

You should use whichever method makes the most sense for the current task. For the given example, that would be str.join:

def doit3():
    ''.join(random.choice(string.letters) for _ in range(R))

If you have a simple operation, concatenation might be good:

dt = '20160108'
tm = '135623'
combined = dt+tm

If you want to add variables into an existing string, use interpolation (or str.format, or format string literals, or whatever):

dt = '20160108'
tm = '135623'
result = 'The date is %s and the time is %s.' % (dt, tm)
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
  • one even faster way would be `''.join([random.choice(string.letters) for _ in range(R)])`. And BTW `string.letters` should be `string.ascii_letters` for python 3 right? – Jean-François Fabre Dec 29 '16 at 10:03
0

It's not a matter of performance but with "template" % (parameters) you have a clear separation between "static" content (the template) and variable parameters. Depending on what kind of string you're creating this makes things a lot more readable (say you're creating an html / rest query, the path is clearly visible in the template and the variable parameters are highlighted)

If at some point you need localization it's easy to see you need to translate only the template part and if you're creating html-requests or sql queries or the like, it's clear you need to escape the variable parts.

Tannin
  • 488
  • 5
  • 11