8

Someone has recently demonstrated to me that we can print variables in Python like how Perl does.

Instead of:

print("%s, %s, %s" % (foo, bar, baz))

we could do:

print("%(foo)s, %(bar)s, %(baz)s" % locals())

Is there a less hacky looking way of printing variables in Python like we do in Perl? I think the 2nd solution actually looks really good and makes code a lot more readable, but the locals() hanging around there makes it look like such a convoluted way of doing it.

10
  • This looks awfully close to stackoverflow.com/questions/3534714/… ... Commented Aug 20, 2010 at 20:50
  • 1
    stackoverflow.com/questions/1550479 (no endorsement of the answers, which I havn't read) Commented Aug 20, 2010 at 20:59
  • 1
    You've said, essentially, that you want Python to be more like Perl. Which aspect of Perl? There's more than one way to format a string. Commented Aug 20, 2010 at 21:16
  • 1
    Just the part where we can format a string by referencing variables directly in the quotes, rather than having to format it outside of the quotes. I just find that strings are a lot more readable when you don't have to read outside the quotes. No break in flow (can't think of a better way to describe it.. urgh) Commented Aug 20, 2010 at 21:32
  • @Greg: What are you talking about? He said exactly what he wants. Commented Aug 20, 2010 at 21:39

5 Answers 5

10

The only other way would be to use the Python 2.6+/3.x .format() method for string formatting:

# dict must be passed by reference to .format()
print("{foo}, {bar}, {baz}").format(**locals()) 

Or referencing specific variables by name:

# Python 2.6
print("{0}, {1}, {2}").format(foo, bar, baz) 

# Python 2.7/3.1+
print("{}, {}, {}").format(foo, bar, baz)    
Sign up to request clarification or add additional context in comments.

4 Comments

This doesn't exactly make it look cleaner.
Just added the specific ones for when referencing the variable directly. The 2.7/3.1+ version is definitely the cleanest of them all in my opinion.
Fine, right up until you start pulling the strings from a localization database. At that point, you have to go back to using explicit orderings because different languages prefer different orders of values. (Really.)
you can use vars() instead of locals(). Also vars(obj) to use obj.__dict__ for the substitutions
5

Using % locals() or .format(**locals()) is not always a good idea. As example, it could be a possible security risk if the string is pulled from a localization database or could contain user input, and it mixes program logic and translation, as you will have to take care of the strings used in the program.

A good workaround is to limit the strings available. As example, I have a program that keeps some informations about a file. All data entities have a dictionary like this one:

myfile.info = {'name': "My Verbose File Name", 
               'source': "My Verbose File Source" }

Then, when the files are processes, I can do something like this:

for current_file in files:
    print 'Processing "{name}" (from: {source}) ...'.format(**currentfile.info)
    # ...

2 Comments

+1 This is a good point. Don't know why someone would downvote it.
Yep, see stackoverflow.com/questions/1550479/… for a thorough discussion on why Explicit is better than implicit. in exactly this context.
3

I prefer the .format() method myself, but you can always do:

age = 99
name = "bobby"
print name, "is", age, "years old"

Produces: bobby is 99 years old. Notice the implicit spaces.

Or, you can get real nasty:

def p(*args):
    print "".join(str(x) for x in args))

p(name, " is ", age, " years old")

2 Comments

Why would you do that? (The nasty part)
@sharvey, the question is asking for unpythonic.
3

Since Python 3.6, you could have what you wanted.

>>> name = "world"
>>> print(f'hello {name}')
hello world

note the string prefix f above

Comments

1

The answer is, no, the syntax for strings in Python does not include variable substitution inthe style of Perl (or Ruby, for that matter). Using … % locals() is about as slick as you are going to get.

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.