PEP:XXX
Title:Concatenation by multi-argument constructors.
Version:$Revision: 32 $
Last-Modified:$Date: 2006-04-12 02:30:20 -0700 (Wed, 12 Apr 2006) $
Author:Beni Cherniavsky <cben at users.sf.net>
Status:Draft
Type:Standards Track
Content-Type:text/x-rst
Created:29-Nov-2003
Python-Version:2.4
Post-History:06-Aug-2001

Contents

Abstract

Python's current ways to concatenate sequences are less convenient than they could be (the + operator requires the operands to have the same type). There is no obvious way to combine dictionaries in a single expression at all. "Concatenating" iterators is supported but is placed in the itertools module.

This PEP proposes a consistent set of extensions to the list(), tuple(), str() and dict() constructors to concatenate several values by giving them multiple arguments. iter() is similarly extended to behave as itertools.ichain(). All arguments are converted in the same ways as a single argument is now converted.

Specification

The list(), tuple(), str() and dict() constructors as well as the iter() function are to be extended to accept multiple arguments.

Motivation

Suppose you want to create a list by concatenating several iterables. You can use the + operator only if they are all of the same type. When the types differ, there is no obvious type for the result, so + raises an exception (taking the type of the left operand would be a bad idea because it's desirable for + to be commutative, if not in values than at least in types). So you have to explicitly convert every object:

list(foo) + list(bar) + list(baz)

This looks redudant and is also sub-optimal because it creates 3 temporal list objects and takes O(N**2) time for N objects. This PEP stems from the simple observation that the notation:

list(foo, bar, baz)

would solve the above problems and has no assigned meaning. The current behaviors allowing to pass 0 or 1 argument would elegantly become special cases of the new behavior.

Whatever holds for lists should also hold for tuples and probably strings. For strings, it's important that each argument is processed exactly as str currently does for a single argument- it's not a simple concatenation of iterables. The new notation would be especailly convenient for strings, potentially replacing string formatting operations where all you need is to convert some values to strings and concatenate the results:

str("=== ", title, " ===")

It also makes sense to extend it to dictionaries. By "concatenating" dictionaries I mean the equivallent of:

d = d1.copy()
d.update(d2)
d.update(d3)

except that a single expression is desired. Surprisingly, there is currently no sane way to do it in Python! The closest candidate is:

dict(d1.items() + d2.items() + d3.items())

Again, it's useful to allow mixing of mapping and sequence-of-pairs arguments and even mixing of positional and keyword arguments. That would make creating a dictionary differing in a single value as easy as:

dict(d, foo=bar)

Last, the iter constructor also accepts iterables so it should also be extended in this way. This extension is already available as itertools.ichain and you can use it for effecient concatenation:

list(ichain(foo, bar))
dict(ichain(foo.items(), bar.items()))

but it would be more convenient to have it available as:

iter(foo, bar)

There is already a two-argument version of iter() but the first argument is a callable rather than an iterable so there is no conflict; perhaps even mixing iterables with callable/sentinel pairs should be allowed.

Docutils System Messages

System Message: WARNING/2 (pep-constr.txt); backlink

"PEP" header must contain an integer; "XXX" is an invalid value.