C
Christoph Zwerschke
Ok, the answer is easy: For historical reasons - built-in sets exist
only since Python 2.4.
Anyway, I was thinking about whether it would be possible and desirable
to change the old behavior in future Python versions and let dict.keys()
and dict.values() both return sets instead of lists.
If d is a dict, code like:
for x in d.keys():
...
or even
for x in sorted(d.keys()):
...
would still work and do the same.
However, the older idiom
k = d.keys()
k.sort()
for x in k:
...
would break (since you cannot sort a map directly).
So it seems not possible to change the behavior since it would break old
code. Maybe keys() and values() could be made deprecated functions,
superseded by keyset() and valueset(), but probably this would not be
worth the effort.
Another related question: Actually, dicts can be considered as
subclasses of sets and thus could inherit a lot of set methods and
operators. Only intersection and union must be treated with care,
because dictionaries must be mappings (i.e. map to exactly one value).
In fact, some inheritance from sets has already been implemented:
For instance, by allowing the set operator "in" for dictionaries,
instead of "has_key".
The len(), clear(), copy() and update() functions can also be
interpreted as inherited from set. The dictionary method popitem() is
actually the inherited set method pop(). (d.pop() without arguments
could actually do the same as d.popitem(); I guess the suffix "item" was
chosen to remind you that it returns a key/value pair, not only a value.)
But could other set methods also be useful?
A dictionary could inherit the remove() and discard() method from sets.
d.remove(x) would do the same as del d[x], but d.discard(x) would not
raise a KeyError if x not in d.
Or, for instance, if
a = { 1:11, 2:12 }; b = { 2:22, 3:13 }, c = { 2:32 }
then
c.issubset(b) == c <= b == True
b.issuperset(c) == b >= c == True
a.difference(b) == a - b == { 1:11 }
a.s.symmetric_difference(b) == a ^ b == { 1:11, 3:13 }
a.update(b) == a |= b == a = { 1:11, 2:22, 3:13 }
a.intersection_update(b) == a &= b == a = { 2:22 }
a.difference_update(b) == a -= b == a = { 1:11 }
a.symmetric_difference_update(b) == a ^= b == a = { 1:11, 3:13 }
Of these, a |= b may be particularly interesting as short notation for
a.update(b).
-- Christoph
only since Python 2.4.
Anyway, I was thinking about whether it would be possible and desirable
to change the old behavior in future Python versions and let dict.keys()
and dict.values() both return sets instead of lists.
If d is a dict, code like:
for x in d.keys():
...
or even
for x in sorted(d.keys()):
...
would still work and do the same.
However, the older idiom
k = d.keys()
k.sort()
for x in k:
...
would break (since you cannot sort a map directly).
So it seems not possible to change the behavior since it would break old
code. Maybe keys() and values() could be made deprecated functions,
superseded by keyset() and valueset(), but probably this would not be
worth the effort.
Another related question: Actually, dicts can be considered as
subclasses of sets and thus could inherit a lot of set methods and
operators. Only intersection and union must be treated with care,
because dictionaries must be mappings (i.e. map to exactly one value).
In fact, some inheritance from sets has already been implemented:
For instance, by allowing the set operator "in" for dictionaries,
instead of "has_key".
The len(), clear(), copy() and update() functions can also be
interpreted as inherited from set. The dictionary method popitem() is
actually the inherited set method pop(). (d.pop() without arguments
could actually do the same as d.popitem(); I guess the suffix "item" was
chosen to remind you that it returns a key/value pair, not only a value.)
But could other set methods also be useful?
A dictionary could inherit the remove() and discard() method from sets.
d.remove(x) would do the same as del d[x], but d.discard(x) would not
raise a KeyError if x not in d.
Or, for instance, if
a = { 1:11, 2:12 }; b = { 2:22, 3:13 }, c = { 2:32 }
then
c.issubset(b) == c <= b == True
b.issuperset(c) == b >= c == True
a.difference(b) == a - b == { 1:11 }
a.s.symmetric_difference(b) == a ^ b == { 1:11, 3:13 }
a.update(b) == a |= b == a = { 1:11, 2:22, 3:13 }
a.intersection_update(b) == a &= b == a = { 2:22 }
a.difference_update(b) == a -= b == a = { 1:11 }
a.symmetric_difference_update(b) == a ^= b == a = { 1:11, 3:13 }
Of these, a |= b may be particularly interesting as short notation for
a.update(b).
-- Christoph