Using percent in a string

A (perhaps) obscure fact - how to use the percent sign in a Python string.

Add this to list of list of things I'm surprised I didn't know about Python. How do you use a percent / modulo ''%'' symbol in a string?

I had to do this the other day and it stumped me. How could it be that in <insert large number of years> I've never had to do this? Because the percent symbol is used for string formatting in Python, it was tricky. And - for the same reason - there had to be a way. But it was missing from the documentation, several text books, and googling didn't show anything. What makes it more confusing is that Python is sensible about when it tries to interpolate the symbol, so that a lot of the time you don't have to do anything clever:

# these work
>>> '%'
'%'
>>> '%%'
'%%'
>>> '%s' % 'foo'
'foo'
>>> 's%ss' % 'foo'
'sfoos'

# this doesn't
>>> '%%s' % 'foo'
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
TypeError: not all arguments converted during string formatting

The trick is to double the percent symbol anytime the string is being formated and you don't want it to be interpolated:

>>> '%%%s' % 'foo'
'%foo'

Of course, you can also solve this problem by just adding string segments together, putting the plain percent in strings that aren't interpolated:

>>> '%' + '%s' % 'foo'
'%foo'

Alternatively, in Python 3, you could just use format and avoid this whole percent shenanigans.

Bonus tip: Another obvious and useful thing: in Python 2.4, the function 'sorted' was added. As opposed to the usual ''sort'' - which rearranges a list inplace - this creates a new list, a previously obvious and odd gap in Python. Not so obviously, it's not a method but a function, that works on any iterable:

# no value is returned from 'sort' so x is None
>>> a = [5, 2, 3, 7]
>>> a.sort()
>>> a [2, 3, 5, 7]
>>> x = a.sort()
>>> x

>>> b = [5, 2, 3, 7]
>>> y = sorted (b)
>>> y
[2, 3, 5, 7]
>>> b
[5, 2, 3, 7]

This makes it suitable for pritning out the keys of a dictionary in order: sorted (d.keys()). See what happens if you don't read your changelogs?