sagar
sagar

Reputation: 1435

In string formatting can I replace only one argument at a time?

Is there any way I can only replace only the first argument only in string formatting? Like in this:

"My quest is {test}{}".format(test="test")

I want the output to be:

"My quest is test {}

The second {} arg I will replace later.

I know I can create a string like:

"My quest is {test}".format(test="test")

and later combine it with remaining string and create new string, but can I do it in one go?

Upvotes: 23

Views: 11730

Answers (6)

MANORIT CHAWDHRY
MANORIT CHAWDHRY

Reputation: 443

You can use replace functionality in python and replace the strings instead of using format, this allows you to do it in any order and replace one string at a time also

x = "{param1} test {param2}"
x = x.replace("{param1}", param1)
x = x.replace("{param2}", param2)

Upvotes: 3

MortenB
MortenB

Reputation: 3547

Use named parameters and leave the others to be replaced with the same.

Use this a lot to "normalize strings" so they fit general patterns upfront:

>>> x = "foo {test} bar {other}"
>>> x = x.format(test='test1', other='{other}') 
>>> x
'foo test1 bar {other}'
>>> x = x.format(other='other1')                
>>> x
'foo test1 bar other1'

Upvotes: 13

Piotr Ćwiek
Piotr Ćwiek

Reputation: 1650

The correct way to achieve this would probably be to subclass string.Formatter class and use its instance instead of the string method:

from string import Formatter
class IncrementalFormatter(Formatter):
    pass  # your implementation
f = IncrementalFormatter()
f.format("hello {name}", name="Tom")

The following Formatter methods would have to be overwritten:

  1. get_value() should return some special object instead of raising LookupError.
  2. get_field() should save field_name argument into this object (or proceed normally if the object is not our special object).
  3. convert_field() should just save conversion argument into this object and do no conversion (or proceed normally...).
  4. format_field() should reconstruct field format string from the special object using its field_name and conversion attributes and format_spec argument of this method (or proceed normally...).

So, for example:

f.format("{greet} {who.name!r:^16s}", greet="hello")

should result in "hello {who.name!r:^16s}", where "who.name" is field_name, "r" is conversion, "^16s" is format_spec and all these three values were re-combined back into "{who.name!r:^16s}", so that it can be used in the next formatting pass.

Additional note: the special object should return itself upon access of any attribute (with .) or item (with []).

Upvotes: 0

Blckknght
Blckknght

Reputation: 104762

If you know when you set up the format string that you'll only be replacing a subset of the values, and you want some other set to remain, you can escape the ones you're not going to fill right away by doubling the brackets:

x = "foo {test} bar {{other}}".format(test="test") # other won't be filled in here
print(x)                              # prints "foo test bar {other}"
print(x.format(other="whatever"))     # prints "foo test bar whatever"

Upvotes: 28

poke
poke

Reputation: 388023

You would have to write your own format function that only makes a single replacement. For example, to give you something to start with (note that this is somewhat vulnerable to bad format strings):

import re
def formatOne(s, arg):
    return re.sub('\{.*?\}', arg, s, count=1)

Used like this:

>>> s = "My quest is {test}{}"
>>> formatOne(s, 'test')
'My quest is test{}'
>>> formatOne(_, ' later')
'My quest is test later'

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160567

The only way you can replace it in the same line is if you replace "{test}" with another bracket. I.e:

s = "My quest is {test}".format(test="test {}").format('testing')

but that doesn't make much sense because you could've just done:

s = "My quest is {test} {}".format('testing', test="test {}")

immediately.

You could keep the result of:

s = "My quest is {test}".format(test="test {}")

So s has a bracket inside it waiting to get replaced and call format on it later on if you need to.

Upvotes: 1

Related Questions