Optional space in python string formatting

Suppose I have 3 python lines, and I can format all 3 of them with two separation spaces between them, as in the following:

h="hello" m="my" w="world" print("{} {} {}".format(h,m,w)) 

or using

 print("%s %s %s" % (h,m,w)) 

Suppose now that I am sure that both h and w have values, but m can be an empty string. The two code snippets described above will lead to the "hello{two speces here}world .

I know that I can use different functions and conditional expressions to format by code, for example, in

 print(h+" " + m+(" " if len(m)>0 else "") + w) 

or select a different format string

 print(("{} {} {}" if len(m)>0 else "{}{} {}").format(h,m,w)) 

based on length m.

My Q: Can this be done using format strings ? (for example, some format modifier that will fill 1 space if its parameter is not empty).

+8
python string-formatting
source share
5 answers

I'm not sure that this is very convenient, but there is a way that generates space or does not depend on the value of the "truth" of the lines:

 h="hello" m="my" w="world" print("{}{}{}{}".format(h," "*bool(m),m,w)) 

result:

 hello my world 

now set m to an empty string, you will get

 hello world 
+4
source share

I'm not sure if this can be done with string formatting.

I would do this using python string join .

 strings = [h, m, w] print " ".join([s for s in strings if len(s)>0]) 

The inside of [s for s in strings if len(s)>0] creates a list with zero lines without zero length. Then " ".join(...) connects them together with a space between.

+3
source share

I believe this is not possible with formatting strings alone.

if you need to use format strings that you could use re module to get rid of extra spaces after applying formatting:

  import re h="hello" m="my" w="world" p = re.compile('\s+') print p.sub(" ","{} {} {}".format(h,m,w)) 

which outputs:

  hello my world 

with an empty string:

  print p.sub(" ","{} {} {}".format(h,"",w)) 

outputs:

  hello world 

Is that what you are after?

+2
source share

I agree with @ Jean-François Fabre's answer, which basically answers my question, as I pointed it out, saying that (at least for now) there is no answer to this question using only string formatting (i.e. if the generated variables are only h, m and w without additional processing).

However, using the concept of Boolean operators in strings, as in his answer, I think I will use:

 print("{}{}{} {}".format(h,m and " " ,m , w)) 

This drawback is that a person reads this feeling that 4 meanings are being formed (which takes place technically, but not semantically), but I think that briefly and simplicity of expression overcomes the negative aspect.

Readability can be improved using parameterized formats, as suggested by @Tsingyi, but using the following:

 print("{}{pad}{} {}".format(h, m , w, pad = m and " ")) 

Note:
NEXT NON-OPERATING CODE DURING LETTERS:
Hopefully in the future, maybe we could do something like:

 print("{}{: >?} {}".format(h,m,w)) 

with semantics "optionally (if m then) align it to the right and the area with one additional space on the left" or

 print("{} {: <?}{}".format(h,m,w)) 

with semantics "optionally (if m then) align it to the left and the site with one additional space to the right"

similar options may be useful for optional formatting currency symbols for example.

 print("{:$>?}{}".format(s)) 

to get either an empty string or $ 123

One final (long) note: at some point during my research on this problem, I thought that I could do something like this:

 def extend_string_formatting(): try: '{:left-pad-if-not-empty}'.format('') except ValueError: original_formatter=str.__format__ def extended_formatter(self, format): if (format == 'left-pad-if-not-empty'): return ' ' + self if self else '' return original_formatter(self, format) str.__format__=extended_formatter extend_string_formatting() 

but it turns out that this leads to:

 Traceback (most recent call last): File "<input>", line 3, in extend_string_formatting ValueError: Invalid format specifier During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 12, in extend_string_formatting TypeError: can't set attributes of built-in/extension type 'str' 

Perhaps this can be achieved with something like the one described here: https://stackoverflow.com/a/212618/

+1
source share

You can use Parametrized formats with the new style string formatting, but you still need to check if m empty or not yourself.

 def fmt(h, m, w): return return '{}{:>{wd}} {}'.format(h, m, w, wd=len(m)+1 if m else 0) >>> fmt('hello', 'my', 'world') 'hello my world' >>> fmt('hello', '', 'world') 'hello world' 
0
source share

All Articles