[Python-ideas] Dart like multi line strings identation

Steven D'Aprano steve at pearwood.info
Sat Mar 31 20:43:30 EDT 2018


On Sat, Mar 31, 2018 at 04:50:03PM +0200, Marius Räsener wrote:

[...]
> What I have in mind is probably best described with an Example:
> 
> print("""
>     I am a
>     multiline
>     String.
>     """)
> 
> the closing quote defines the "margin indentation" - so in this example all
> lines would get reduces by their leading 4 spaces, resulting in a "clean"
> and unintended string.

Backwards compatibility rules this out. I have many strings that 
intentionally include indents and you will annoy me no end if you 
make those indents disappear :-)

But having said that, for every one of those, I have a lot more where 
the indents are annoying. I either outdent the lines:

def spam():
    text = """some text
another line
and a third one
"""
    print(text)


or I use implicit string concatenation:

def spam():
    text = ("some text\n"
            "another line\n"
            "and a third\n")
    print(text)


neither of which I'm really happy with.

The ideal solution would:

- require only a single pair of starting/ending string delimiters;

- allow string literals to be indented to the current block, for 
  the visual look and to make it more convenient with editors
  which automatically indent;

- evaluate without the indents;

- with no runtime cost.


One solution is to add yet another string prefix, let's say d for 
dedent, but as Terry and others point out, that leads to a combinational 
explosion with f-strings and r-strings already existing.

Another possibility is to make dedent a string method:

def spam():
    text = """\
           some text
           another line
           and a third
           """.dedent()
    print(text)

and avoid the import of textwrap. However, that also imposes a runtime 
cost, which could be expensive if you are careless:

for x in seq:
   for y in another_seq:
      process("""/
              some large indented string
              """.dedent()
              )

(Note: the same applies to using textwrap.dedent.)

But we could avoid that runtime cost if the keyhole optimizer performed 
the dedent at compile time:

    triple-quoted string literal
    .dedent()

could be optimized at compile-time, like other constant-folding.

Out of all the options, including the status quo, the one I dislike the 
least is the last one:

- make dedent a string method;

- recommend (but don't require) that implementations perform the 
  dedent of string literals at compile time;

  (failure to do so is a quality of implementation issue, not a bug)

- textwrap.dedent then becomes a thin wrapper around the string method.


Thoughts?





-- 
Steve


More information about the Python-ideas mailing list