[Python-3000] sets in P3K?
Josiah Carlson
jcarlson at uci.edu
Thu Apr 27 00:55:43 CEST 2006
"Guido van Rossum" <guido at python.org> wrote:
> On 4/26/06, Josiah Carlson <jcarlson at uci.edu> wrote:
> >
> > Edward Loper <edloper at gradient.cis.upenn.edu> wrote:
> > >
> > > I think that a significant motivation for people that propose set
> > > literals is that the following is just plain ugly:
> > >
> > > s = set([1,2,3])
> > >
> > > It seems much more natural to write:
> > >
> > > s = set(1, 2, 3)
> >
> > I agree.
> >
> > > However, it is fairly common to want to build a set from a collection,
> > > an iterator, or a genexp. With the current notation, all three of these
> > > are easy. But with this "more natural" notation, they're no longer
> > > possible without resorting to varargs (which would create an unnecessary
> > > imtermediary tuple).
> >
> > Right now you are manually creating an intermediate list or tuple to
> > pass to set, so this wouldn't seem to be a significant change to me
> > (it's just an argument semantic addition).
>
> I have no idea what you mean by "argument semantic addition".
Arguments to a function have a specified semantic result. Allow all of
all the previously working argument passing semantics to work as they
always did (sequences), then add a new allowed argument passing semantic.
> I don't think this form (set(1, 2, 3)) will ever fly, because it would
> makes set(x) ambiguous. Currently, this interprets x as an iterable
> and produces a set with the elements produced by iterating over x. But
> if set(x, y) is a set of two elements, then set(x) should be a set of
> one element, *regardless of the type of x*.
The ambiguity isn't when using set(1), it's when using set((1,2)). set
(1) has one very clear semantic meaning: create a set of one item where
that item is 1. However, set((1,2)) has two meanings: create a set of
two items, one of those items being 1, the other item being 2 - or
create a set of a single item, where that single item is a tuple.
> Curiously, min() and max() successfully use the same overloading.
> However, these don't have the same problem, because min() or max() of
> one value makes no sense, so it's safe to define these such that if
> they are called with a single argument, the argument is assumed to be
> an iterable. But constructing a set() of one value *does* make sense
> (and already has a meaning) so the overloading fails here.
Indeed, but only with immutable iterable sequences. Mutable iterable
sequences are unambiguous (they don't hash(), so can't be an entry in
and of themselves).
def _set(*args):
if len(args) > 1:
#one unambiguous case
return set(args)
arg = args[0]
try:
#catches non-sequences
_ = iter(arg)
except TypeError:
#another unambiguous case
return set((arg,))
try:
#catches mutable sequences
_ = hash(arg)
except:
#unambiguous for non-hashables
return set(arg)
else:
#ambiguous for any immutable iterable sequence...
return set(arg)
However, being that this is the Py3k list, and the only ambiguous case
is that of a single immutable sequence argument to set(), we could
state an execution semantic and call it sufficient.
Being that set(<immutable iterable sequence>) right now results in the
insertion of each item from that sequence into a new set (set((1,2)) ->
set([1,2]) ), we wouldn't need to change the obvious (at least to some)
meaning, or really "the way it works now" meaning.
On the other hand, I note that both Raymond and Guido are saying -1, so
I'll not push it (though I'm also still against more literal syntax),
even though one can come to an almost obvious signature.
> I find the many attempts to come up with a reasonable way to construct
> a set from a list of given values; I hope that {x, y} can still come
> out as a winner, with set(x) useful to construct a set from a
> pre-existing iterable. Note that set(range(10)) is a set with 10
> elements; {range(10)} of course would be a set with one element.
Or really {tuple(range(10))}?
- Josiah
More information about the Python-3000
mailing list