25

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?

1
  • Can you give more clear example to demonstrate what you want? Your question is not clear. Commented Nov 18, 2016 at 7:36

7 Answers 7

30

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"
Sign up to request clarification or add additional context in comments.

3 Comments

So if I need to format, let's say 4 times, I need to wrap some of the placeholders into 4 pairs of brackets like so: my_str = "{first}, {{second}}, {{{third}}}, {{{{fourth}}}}"?
No, you need to double each time: "{first}, {{second}}, {{{{third}}}}, {{{{{{{{fourth}}}}}}}}". You might want to use one of the other approaches (like second="{second}" if this is something you really need to do.
I believe this solution is not scalable. If you want to format the parameters in different order depending on some condition, how are you going to modify the base string before that? I see no way to do that in a short, feasible way.
16

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'

4 Comments

I like this solution as you dont need to encapsulate parameters in mulriple {}
This response is underrated.
This won't work if the format requires e.g. an int.
@MartinPecka format won't care if you use a string the first time and an int the second. I think this solution is brilliant.
5

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)

1 Comment

You probably want to use str(param1) if it isn't a string to start with.
3

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'

1 Comment

This answer inspired me. Thank you. I ended up creating an easier one for my case: def formatone(s: str, field: str, value: str) -> str: idx_begin = s.find('{'+field+'}') idx_end = idx_begin + len(field) + 2 return s[:idx_begin] + value + s[idx_end:]
1

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.

2 Comments

I don't think that solution is good, as it relies heavily on the structure of the string outside the format. It's also obviously not the only was to tackle the problem.
You can always do this: "{a} {b}".format(a="foo",b="{b}"), so as not to rely on the way the string is set up, but only the names. Still not perfect however
0

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 []).

Comments

-1

You can break the string in two or more strings when assigning.

s = "{first} and " + "{second}".format(second=2)
print(s)
s.format(first=1)

Output:

>>> s
'{first} and 2'
>>> s.format(first=1)
'1 and 2'

1 Comment

You are assuming that assignment and formatting are occurring at the same time. Maybe sometimes it is, but I wouldn't count on it.

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.