25

Given:

dict = {"path": "/var/blah"}
curr = "1.1"
prev = "1.0"

What's the best/shortest way to interpolate the string to generate the following:

path: /var/blah curr: 1.1 prev: 1.0

I know this works:

str = "path: %(path)s curr: %(curr)s prev: %(prev)s" % {"path": dict["path"],"curr": curr, "prev": prev}

But I was hoping there is a shorter way, such as:

str = "path: %(path)s curr: %s prev: %s" % (dict, curr, prev)

My apologies if this seems like an overly pedantic question.

8 Answers 8

57

You can try this:

data = {"path": "/var/blah",
        "curr": "1.1",
        "prev": "1.0"}

s = "path: %(path)s curr: %(curr)s prev: %(prev)s" % data
Sign up to request clarification or add additional context in comments.

Comments

29

And of course you could use the newer (from 2.6) .format string method:

>>> mydict = {"path": "/var/blah"}
>>> curr = "1.1"
>>> prev = "1.0"
>>>
>>> s = "path: {0} curr: {1} prev: {2}".format(mydict['path'], curr, prev)
>>> s
'path: /var/blah curr: 1.1 prev: 1.0'   

Or, if all elements were in the dictionary, you could do this:

>>> mydict = {"path": "/var/blah", "curr": 1.1, "prev": 1.0}
>>> "path: {path} curr: {curr} prev: {prev}".format(**mydict)
'path: /var/blah curr: 1.1 prev: 1.0'
>>>

From the str.format() documentation:

This method of string formatting is the new standard in Python 3.0, and should be preferred to the % formatting described in String Formatting Operations in new code.

1 Comment

Using str.format he could write "path: {mydict[path]} curr: {curr} prev: {prev}".format(mydict=mydict, curr=curr, prev=prev) or even locals() for the argument to format, "path: {mydict[path]} curr: {curr} prev: {prev}".format(**locals())
18

Why not:

mystr = "path: %s curr: %s prev: %s" % (mydict[path], curr, prev)

BTW, I've changed a couple names you were using that trample upon builtin names -- don't do that, it's never needed and once in a while will waste a lot of your time tracking down a misbehavior it causes (where something's using the builtin name assuming it means the builtin but you have hidden it with the name of our own variable).

Comments

13

Maybe:

path = dict['path']
str = "path: %(path)s curr: %(curr)s prev: %(prev)s" % locals()

I mean it works:

>>> dict = {"path": "/var/blah"}
>>> curr = "1.1"
>>> prev = "1.0"
>>> path = dict['path']
>>> str = "path: %(path)s curr: %(curr)s prev: %(prev)s" % locals()
>>> str
'path: /var/blah curr: 1.1 prev: 1.0'

I just don't know if you consider that shorter.

4 Comments

Avoid uses of locals() & globals() :(
@dzen Why avoid locals()? I've tried searching for this advice elsewhere and I'm not finding much.
Using locals() means that it is not clear which variables you are actually. If you wanted to pylint your code, pylint might well report that some variables were not used even though you referenced them implicitly with locals(). Pylint would have to examine all you string format statements for such implicit use. So it is a shortcut whose implications you should understand before using.
In case the template string is user input, you don't want them to be able to see local variables, in case there are passwords or something. Also "explicit is better than implicit" according to pep20 (don't follow pep blindly, but maybe in this case it works).
8

You can also (soon) use f-strings in Python 3.6, which is probably the shortest way to format a string:

print(f'path: {path} curr: {curr} prev: {prev}')

And even put all your data inside a dict:

d = {"path": path, "curr": curr, "prev": prev}
print(f'path: {d["path"]} curr: {d["curr"]} prev: {d["prev"]}')

1 Comment

In python3 print is a function, which requires parentheses.
5

You can do the following if you place your data inside a dictionary:

data = {"path": "/var/blah","curr": "1.1","prev": "1.0"}

"{0}: {path}, {1}: {curr}, {2}: {prev}".format(*data, **data)

1 Comment

This is the best one.
3

Update 2016: As of Python 3.6 you can substitute variables into strings by name:

>>> origin = "London"
>>> destination = "Paris"
>>> f"from {origin} to {destination}"
'from London to Paris'

Note the f" prefix. If you try this in Python 3.5 or earlier, you'll get a SyntaxError.

See https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings

Comments

1

If you don't want to add the unchanging variables to your dictionary each time, you can reference both the variables and the dictionary keys using format:

str = "path {path} curr: {curr} prev: {prev}".format(curr=curr, prev=prev, **dict)

It might be bad form logically, but it makes things more modular expecting curr and prev to be mostly static and the dictionary to update.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.