UserDict's has_key() and get() should use __getitem__()
Hamish Lawson
hamish_lawson at yahoo.co.uk
Wed Apr 5 06:44:01 EDT 2000
[This is a modified version of an earlier posting for which I
didn't get any responses. I'm trying again with what I'm hoping
might be a clearer exposition.]
The UserDict class in the standard library provides a framework
for defining your own dictionary-like classes. However I think
their may be an anomaly in how it is currently implemented (up
to 1.5.2). I think that most people would expect that if the
following statement succeeded:
print d['Joe']
then the following line would evaluate true:
print d.has_key('Joe')
However, under the current implementation of UserDict, if you
redefine __getitem__() in your own UserDict-derived class, you
will probably also have to redefine has_key() and get() (and
maybe others) in order to have them behave as expected. This
wholescale redefining is caused by the fact that UserDict's
has_key() and get() methods don't make use of the class's own
__getitem__() method in determining whether a key exists, as
shown in the extract below:
def __getitem__(self, key):
return self.data[key]
def has_key(self, key):
return self.data.has_key(key)
def get(self, key, failobj=None):
return self.data.get(key, failobj)
My contention is that the behaviour we expect from get() and
has_key() is intimately bound up with how __getitem__() behaves,
and this should be reflected in get() and has_key() making use
of __getitem__():
def has_key(self, key):
try:
self[key]
return 1
except KeyError:
return 0
def get(self, key, failobj=None):
try:
return self[key]
except KeyError:
return failobj
It is now possible to redefine __getitem__() in a derived class
and have has_key() and get() behave as expected, without having
to redefine them also.
(It may be that other methods in UserDict should also be
reimplemented along these lines - I've not looked yet.)
Is there some reason why this isn't the right thing to do?
Assuming it is, I'd like to get this change into Python 1.6.
Hamish Lawson
-----------------------------------------------------------
PS: Below is an example demonstrating how the semantics of
has_key() and get() get broken under the current version of
UserDict when you redefine only __getitem__() in a derived class.
import UserDict, string
class CaselessDict(UserDict):
"A dictionary class with case-insensitive keys"
def __setitem__(self, key, value):
self.data[string.lower(key)] = value
def __getitem__(self, key):
return self.data[string.lower(key)]
d = CaselessDict()
d['Joe'] = "Sue"
print d['jOE'] # prints "Sue"
print d.has_key('jOE') # prints 0 but expected 1
print d.get('jOE', None) # prints None but expected "Sue"
* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!
More information about the Python-list
mailing list