tags:

views:

186

answers:

4

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.

+6  A: 

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)    
jathanism
This doesn't exactly make it look cleaner.
Glenn Maynard
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.
jathanism
@jathanism: 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.)
Donal Fellows
you can use `vars()` instead of `locals()`. Also `vars(obj)` to use `obj.__dict__` for the substitutions
gnibbler
+1  A: 

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")
carl
Why would you do that? (The nasty part)
sharvey
@sharvey, the question is asking for unpythonic.
carl
+1  A: 

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.

pdc
+1  A: 

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)
    # ...
leoluk
+1 This is a good point. Don't know why someone would downvote it.
gnibbler