On Apr 1, 2020, at 20:59, Steven D'Aprano <[email protected]> wrote:
>
> Nevertheless, you do make a good point. It may be that StringIO is not
> the right place for this. That can be debated without dismissing the
> entire idea.
I think it’s worth separating the two.
There is a legitimate desire for a “better” way to build strings than str.join.
And a string builder type is one obvious solution, as used in many other
languages, like Java. To be worth adding, this string builder type should be
more discoverable than str.join, and at least as readable, and close to as
efficient in both time and space. Ideally, it should be more readable to people
with a visceral dislike of str.join, and be significantly better in space (by
not retaining all of the input strings for the entire length of the building
process) on all Python implementations, and there should also be an easy to use
backport.
Almost none of this is true for StringIO.__iadd__, but all of it could easily
be true for a new string.StringBuilder (using the name I think Stephen
suggested). It’s an obvious name, that will probably be the first thing anyone
finds in any reasonable search for how to do a string builder in Python. Once
found, the meaning is pretty clear. And its help or docs will be useful,
concise, and to the point instead of being all about irrelevant and confusing
file stuff with += buried somewhere in the middle as a synonym for write. It
can’t be easily misused (e.g., even people who know StringIO enough to suggest
using it as a string builder mistakenly think `sb = StringIO('abc'):
sb.write('def')` will append rather than overwrite). It can be documented to be
roughly as fast as str.join but without retaining all of the input strings, on
all implementations, which isn’t true for StringIO (which saves no space on
some implementations, like CPython, and saves space at the cost of wasting a
lot of time on others). It can have a better API—take an initial string on
construction, give a useful repr for debugging, etc. Once there are pure-Python
and C implementations, backporting them should be trivial—and, because it’s a
new class rather than a change to an existing one, using the backport will be
trivial too:
try:
from string import StringBuilder
except ImportError:
from stringbuilder import StringBuilder # pip install this
sb = StringBuilder()
for thing in things:
sb += make_a_string(thing)
s = str(sb)
And of course people who only need to support 3.10+ could just import directly
without the backport.
This would still violate TOOWDTI. And that koan really isn’t just a joke; it’s
a serious guideline, just not an absolute one. Adding a second way to do
something faces an extra hurdle that has to be overcome, beyond the usual
hurdle of conservativeness, but plenty of proposals have overcome that
hurdle—str.format, for example, had obvious huge costs from two ways to do
something so basic, but its benefits (especially in extensibility) were even
huger. Here, the benefits aren’t as large, but the cost isn’t either. So it’s
at least arguable that it’s worth doing—not because we should ignore TOOWTDI,
but because the benefits in discoverability, readability, and maybe space
efficiency outweigh the cost of two ways to do it.
If someone wants to propose a string builder that meets that burden (and write
the Python and C implementations), I’d be +0.5. But StringIO.__iadd__ does not,
which is why I’m -1 on it.
(For a third-party library, I’m not sure I’d bother with a C implementation—it
can just check if CPython and if so use a str as its buffer… but for a builtin
member of a stdlib module, that’s probably not acceptable.)
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/NEKQSVS4UCFIJTCW4Y6IL4D6PHHQRBNQ/
Code of Conduct: http://python.org/psf/codeofconduct/