[Python-ideas] Another attempt at a sum() alternative: the concatenation protocol
Oscar Benjamin
oscar.j.benjamin at gmail.com
Tue Jul 16 13:06:15 CEST 2013
On 16 July 2013 11:37, Ronald Oussoren <ronaldoussoren at mac.com> wrote:
>
> On 16 Jul, 2013, at 12:21, Oscar Benjamin <oscar.j.benjamin at gmail.com> wrote:
>
>> On 16 July 2013 07:50, Nick Coghlan <ncoghlan at gmail.com> wrote:
>>> I haven't been following the sum() threads fully, but something Ron
>>> suggested gave me an idea for a concatenation API and protocol. I
>>> think we may also be able to use a keyword-only argument to solve the
>>> old string.join vs str.join problem in a more intuitive way.
>>
>> The sum() threads have highlighted one and only one problem which is
>> that people are often using (or at least suggesting to use) sum() in
>> order to concatenate sequences even though it has quadratic
>> performance for this. The stdlib already has a solution for this:
>> chain. No one in the sum threads has raised any issue with using chain
>> (or chain.from_iterable) except to argue that it is not widely used.
>>
>> If people are using sum() to concatenate lists then this should be
>> taken not as evidence that a new solution needs to be found but as
>> evidence that chain is not sufficiently well-known. The obvious
>> solution to that is not to implement a new protocol but to make the
>> existing solution more well known i.e. move chain.from_iterable to
>> builtins and rename it (the obvious choice being concat).
>>
>>> def concat(start, iterable, *, interleave=None):
>>> try:
>>> build = start.__concat__
>>> except AttributeError:
>>> result = start
>>> if interleave is None:
>>> for x in iterable:
>>> result += x
>>> else:
>>> for x in iterable:
>>> result += interleave
>>> result += x
>>> else:
>>> result = build(iterable, interleave=interleave)
>>
>> That doesn't seem like a very nice signature e.g.:
>>
>> concat(lines[0], lines[1:], interleave='\n')
>>
>> is not as good as
>>
>> '\n'.join(lines)
>>
>> It's worse with an iterator:
>>
>> it = iter(iterable)
>> try:
>> start = next(it)
>> except StopIteration:
>> result = ''
>> else:
>> result = concat(start, it, interleave=sep)
>>
>> Or have I misunderstood?
>
> concat('', iterable, interleave=sep) should work.
Not with the code as shown. The result would be prepended with sep.
Oscar
More information about the Python-ideas
mailing list