del and sets proposal

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Oct 4 21:05:37 EDT 2008


On Sat, 04 Oct 2008 18:36:28 +0200, Bruno Desthuilliers wrote:

>> Yes I know that sets have a remove method (like lists), but since
>> dictionaries don't have a remove method, shouldn't sets behave like
>> more like dictionaries and less like lists?  IMHO del for sets is quite
>> intuitive.
> 
> For lists, del a[x] means 'remove item at index x'. For dicts, del a[x]
> means 'remove key:value pair which key is x'. In both cases, del a[x] is
> meaningful because a[x] is meaningful. Sets are neither ordered nor
> indexed, and can't be subscripted. So "del aset[x]" is IMHO as
> meaningless as 'aset[x]' is. Using this syntax for an operation which
> semantic is the same as alist.remove(x) would be at best inconsistent
> and confusing.

Consider the mutable built-in collections set, dict and list, and how 
they remove elements:

aset.remove(x)
alist.remove(x)
del adict[x]

Would it really be "confusing" if sets used the same interface as dicts 
use? I don't think so. What else could "del aset[x]" mean other than 
"delete element x"?

Lists are the odd one out, because del alist[x] is used to remove the 
element at position x, rather than removing an element x. But because 
sets are unordered, there's no ambiguity between element x and the 
element at position x. In that regard, sets are just like dicts, and it 
is a perfectly reasonable position to take that hypothetically sets could 
use "del aset[x]" instead of "aset.remove(x)".

But on the other hand, if you can write "del aset[x]", why can't you 
write "y = aset[x]" or "aset[x] = z"? Neither of these seem useful or 
sensible, although at a stretch we could make "y = aset[x]" equivalent to 
"y = x in aset".

Although there's no technical reason why sets can't have a __delitem__ 
method but no __getitem__ and __setitem__ methods, for consistency it 
does seem rather unusual. 

All this may seem academic, but consider the Bag (Multiset) data type. 
With a Bag, you need to have two commands: "remove element x entirely", 
and "remove one copy of element x only". To my mind, the natural API for 
that is:

del abag[x]  # remove element x entirely
abag.remove(x)  # remove one copy of element x only



-- 
Steven



More information about the Python-list mailing list