lofidevops
lofidevops

Reputation: 16972

Can I express named Python string arguments more succintly?

I know of two ways to include named arguments in a string:

name = "Mary"
pet = "lamb"

# option 1
message = "%(name)s had a little %(pet)s" % {"name": name, "pet": pet}
print(message)

# option 2
message = "{name} had a little {pet}"
message.format(name = name, pet = pet)
print(message)
# I'm not actually sure if `name = name` works, usually these are different

I don't think either of these is very readable. Is there any way to reduce the number of times I repeat variable names here?

It is important that the string arguments are named (not empty) so that:

Upvotes: 2

Views: 158

Answers (5)

DevLounge
DevLounge

Reputation: 8437

With an object:

person.name = 'foo'
person.age = 12

You can do:

print '{name} is {age} old'.format(**person.__dict__)

With a dictionary:

a = {'name': 'foo', age: 12}
print '{name} is {age} old'.format(**a)

With a list/tuple/set/namedtuple:

a = [1,2,3]
b = (1,2,3)
c = set([1,2,3,1])

from collections import namedtuple
Foo = namedtuple('Foo', 'x y z')
foo = Foo(1,2,3)
print '{} {} {}'.format(*foo)


print '{} {} {}'.format(*a)
print '{} {} {}'.format(*b)
print '{} {} {}'.format(*c)
print '{} {} {}'.format(*foo)

However, the namedtuple is more than a tuple, it is also an object, so you can also do this:

print '{x} {z} {y}'.format(**foo._asdict())

The list could be longer, I'll stop here, but now you get an idea...

Upvotes: 5

lofidevops
lofidevops

Reputation: 16972

Using a dictionary reduces the number of times you need to reference the argument names...

# stand-in for actual calculations
madlib = {}
madlib["name"] = "Mary"
madlib["pet"] = "lamb"

# this is the simplified bit
message = "%(name)s had a little %(pet)s" % madlib
print(message)

(Only remaining question, then, is if using a dictionary for storage is un-Pythonic.)

Upvotes: 1

DSM
DSM

Reputation: 353149

Sometimes when I'm lazy I use locals() for this purpose:

>>> name = "Mary"
>>> pet = "lamb"
>>> "{name}, {name}, quite contrary, how does your {pet} grow?".format(**locals())
'Mary, Mary, quite contrary, how does your lamb grow?'

This doesn't require construction of a special object, but that could just as easily be viewed as a weakness, not a strength.

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107297

you are not forced to use variable names inside the bracket , you can use empty {} :

>>> "{} had a little {}".format(name,pet)
'Mary had a little lamb'

also you can use string.Template:

>>> import string
>>> new_style = string.Template('$i had a little $j')
>>> print new_style.substitute(i='Mary',j='lamb')
Mary had a little lamb
>>> print new_style.substitute({'i':'Mary','j':'lamb'}) # use dictionary
Mary had a little lamb

Upvotes: 0

anon582847382
anon582847382

Reputation: 20371

You can just have empty {} brackets in the format string. And by the way in the second one, you need to set the call to format equal to a variable as it doesn't work in-place:

message = '{} had a little {}'.format(name, pet)  # < v2.7 needs numbers in brackets.

Upvotes: 2

Related Questions