__contains__ vs. __getitem__

D

David Isaac

I have a subclass of dict where __getitem__ returns None rather than
raising KeyError for missing keys. (The why of that is not important for
this question.)

I was delighted to find that __contains__ still works as before
after overriding __getitem__. So even though instance['key']
does not raise KeyError, I still get (as desired) 'key' in instance ==
False.

Looking forward:
Can I count on this independence of __getitem__ and __contains__?
I would like to understand whether it will be safe to count on this
behavior.

Thank you,
Alan Isaac
 
B

Bruno Desthuilliers

David said:
I have a subclass of dict where __getitem__ returns None rather than
raising KeyError for missing keys. (The why of that is not important for
this question.)

Well, actually it may be important... What's so wrong with d.get('key')
that you need this behaviour ?
 
E

enigmadude

That's a vague question, so the obligatory "it depends" response
applies here.

If you want to guard against the unexpected, perhaps it's a good idea
to write unit tests rather than to take someone's word that it *should*
work okay every time, in every case, no matter what you're doing with
the data. Think of what behavior would be disasterous (whether it seems
possible or not), then write a test for that behavior. Also write tests
for things that "obviously" *should* hold true... just to make sure
they hold true.

Maybe you can't think of ways that this class could possibly screw
things up, but it's always nice to have reassurance anyway :) The
closest thing to certainty about code is to test it.
 
P

Pedro Werneck

Looking forward:
Can I count on this independence of __getitem__ and __contains__?
I would like to understand whether it will be safe to count on this
behavior.


With the builtin 'dict' implementation, dict.__contains__() use the
dict_has_key() C function, and does not touch your subclass __getitem__
python method. I don't think it can be called 'safe'... it may lead to
very inconsistent behavior. It's like overridind both __eq__ and __ge__
with a different behavior. It's better for you to override
__contains__() too.
 
D

David Isaac

Bruno Desthuilliers said:
Well, actually it may be important... What's so wrong with d.get('key')
that you need this behaviour ?

I want to use the mapping with string interpolation.

Alan Isaac
 
B

Bruno Desthuilliers

David said:
I want to use the mapping with string interpolation.
Well, this makes sens... But then why not use a plain dict to collect
data, and wrap it in a special one just before using it for
interpolation ? ie:

class MyDictWrapper(object):
def __init__(self, d, default=None):
self._d = d
self._default = default
def __getitem__(self, key):
return self._d.get(key, self._default)


def render(d):
tpl = "%(who)s says '%(say)s' and the %(what)s is %(state)s."
return tpl % MyDictWrapper(d)

This would avoid any potential trouble with using a strange kind of dict
in other parts of the code...

My 2 cents...
 
A

Alex Martelli

Pedro Werneck said:
With the builtin 'dict' implementation, dict.__contains__() use the
dict_has_key() C function, and does not touch your subclass __getitem__
python method. I don't think it can be called 'safe'... it may lead to
very inconsistent behavior. It's like overridind both __eq__ and __ge__
with a different behavior. It's better for you to override
__contains__() too.

I think it's perfectly safe -- that's what defaultdict in Python 2.5
does, after all.


Alex
 
A

Alex Martelli

Bruno Desthuilliers said:
Well, this makes sens... But then why not use a plain dict to collect
data, and wrap it in a special one just before using it for
interpolation ? ie:

Using a single container (and being able to modify and use it fluidly)
is simply handier. That's what defaultdict in Python 2.5 is for, btw.


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top