Feature Request: `operator.not_in`
Matthew Gilson
m.gilson1 at gmail.com
Fri Apr 19 15:23:19 EDT 2013
On 4/19/13 2:27 PM, Terry Jan Reedy wrote:
> On 4/19/2013 10:27 AM, Matthew Gilson wrote:
> ) It seems to me that the operator module should have a `not_in` or
>> `not_contains` function. It seems asymmetric that there exists a
>> `is_not` function which implements `x is not y` but there isn't a
>> function to represent `x not in y`.
>
> There is also no operator.in.
True. I'm not arguing that there should be ...
> There is operator.contains and operator.__contains__.
Thankfully :-)
>
> There is no operator.not_contains because there is no __not_contains__
> special method. (Your point two, which I disagree with.)
>
But there's also no special method `__is_not__`, but there's a
corresponding `is_not` in the operator module so I don't really see that
argument. It's a matter of functionality that I'm thinking about in the
first part.
itertools.starmap(operator.not_in,x,y)
vs.
itertools.starmap(lambda a,b: a not in b,x,y)
Pretty much every other operator in python (that I can think of) has an
analogous function in the operator module.
>> 2) I suspect this one might be a little more controversial, but it seems
>> to me that there should be a separate magic method bound to the `not in`
>> operator.
>
> The reference manual disagrees.
> "The operator not in is defined to have the inverse true value of in."
I would still leave that as the default behavior. It's by far the most
useful and commonly expected. And I suppose if you *can't* have default
behavior like that because that is a special case in itself, then that
makes this second part of the request dead in the water at the outset
(and I can live with that explanation).
>
>> Currently, when inspecting the bytecode, it appears to me
>> that `not x in y` is translated to `x not in y` (this supports item 1
>> slightly). However, I don't believe this should be the case. In
>> python, `x < y` does not imply `not x >= y` because a custom object can
>> do whatever it wants with `__ge__` and `__lt__` -- They don't have to
>> fit the normal mathematical definitions.
>
> The reason for this is that the rich comparisons do not have to return
> boolean values, and do not for numarray arrays which, I believe,
> implement the operators itemwise.
>
Yes, you're correct about numpy arrays behaving that way. It can be
very useful for indexing them.
It would also be fine for a special method `__not_contains__` to be
expected to return a boolean value as well. It could still be very
useful. Consider a finite square well from quantum mechanics. I could
define `in` for my particle in the square well to return `True` if there
is a 70% chance that it is located in the well (It's a wave-function, so
it doesn't have a well defined position -- the particle could be anyway,
but 7 out of 10 measurements will tell me it's in the well). It might
be nice if I could define `not in` to be `True` if there is only a 30%
chance that it is in the well. Of course, this leaves us with a
no-man's land around the 50% mark. Is it in the well or not? There's
no telling. I'm sure you could argue that this sort of thing *could* be
done with rich comparisons, but I would consider that a deflection from
the point at hand. It seems it should be up to the user to design the
API most suited for their task. Or what about a `Fraternity` class.
Are the new pledges in the fraternity or not? Maybe they should be
considered neither in, nor out until pledge season is over.
> > I don't see any reason why containment should behave differently.
>
> 'Design by analogy' is tricky because analogies often leave out
> important details. __contains__ *is* expected to return true/false.
>
> " object.__contains__(self, item)
> Called to implement membership test operators. Should return true
> if item is in self, false otherwise"
>
> --
> Terry Jan Reedy
>
>
More information about the Python-list
mailing list