[Python-ideas] Another attempt at a sum() alternative: the concatenation protocol

Ronald Oussoren ronaldoussoren at mac.com
Tue Jul 16 12:37:28 CEST 2013


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.

Ronald



More information about the Python-ideas mailing list