[Python-ideas] Non-boolean return from __contains__

Alex Gaynor alex.gaynor at gmail.com
Sun Jul 25 20:15:21 CEST 2010

Recently I've been wondering why __contains__ casts all of it's
returns to be boolean values.  Specifically I'd like to propose that
__contains__'s return values be passed directly back as the result of
the `in` operation.  As a result I'd further propose the introduction
of __not_contains__, which is the `not in` operator.  The primary
usecase for this is something like an expression recorder.  For
example in SQLAlchemy one can do:

User.id == 3, but not User.id in SQLList([1, 2, 3]), because it returns a
bool always.  __not_contains__ is needed to be the analog of this, as
it cannot be merely be a negation of __contains__ when it's returning
a non-bool result.

There should be no backwards compatibility issues to making
__contains__ return non-bools, unless there is code like:

  x = y in foo
  assert type(x) is bool

However, for __not_contains__ I'd propose the default implementation be:

   def __not_contains__(self, val):
       x = val in self
       if type(x) is not bool:
           raise TypeError("%s returned a non-boolean value from
__contains__ and didn't provide an implementation of
       return not x

This is not perfect (and it's at odds with the fact that __ne__
doesn't return not self == other), but it seems to allow both the
desired flexibility and backwards compatibility.

I'm not sure if this is something that'd be covered by the language
moratorium, but if not I can try putting together a patch for this.


"I disapprove of what you say, but I will defend to the death your
right to say it." -- Voltaire
"The people's good is the highest law." -- Cicero
"Code can always be simpler than you think, but never as simple as you
want" -- Me

More information about the Python-ideas mailing list