The % operator on strings isn't exactly a concatenation like the + operator is.
With % you're actually substituting placeholders in the string on the left side of % with values from the right side.
So you could have something like this:
"This is my %s string" % "fantastic"
would yield:
This is my fantastic string
See how you're not concatenating the strings but "inserting" into the string on the right side.
See the documentation for more details.
Update:
As pointed out in the comments below, there are two "issues" with this. As of Python 2.5, this is actually the "old" way of doing string substitution. These days the following format is preferred (kudos to asmacdo)
"This is my {adjective} string".format(adjective='fantastic')
As well in the comments (thanks ErlVolton) I should explain that the "%s" refers to a string substitution. That is, the value that gets put in there should be a string. Similarly you can have integer substitution ("%d"), decimal floating point substitution ("%f") and, as in the case of the original question, you can substitute boolean values with "%r". You can also do a lot more formatting (vary the number of decimal places for a floating point number, pad numbers with leading zeros etc.) which is explained much better in the docs.
Finally, it's worth mentioning that you can substitute multiple values into a string but that changes the syntax a tiny bit. Instead of having a single value after the % operator you need to use a tuple. Example:
"this %s substitutes strings, booleans (%r) and an integer (%d)" % ('string', True, 42)
would yield:
this string substitutes strings, booleans (True) and an integer (42)