Skip to content

Commit 218f05e

Browse files
committed
in_ and not_in
1 parent 34e4d32 commit 218f05e

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

Doc/library/operator.rst

+10
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,16 @@ Operations which work with sequences (some of them with mappings too) include:
208208
Return ``a + b`` for *a* and *b* sequences.
209209

210210

211+
.. function:: in_(a, b)
212+
213+
Return the outcome of the test ``a in b``.
214+
215+
216+
.. function:: not_in(a, b)
217+
218+
Return the outcome of the test ``a not in b``.
219+
220+
211221
.. function:: contains(a, b)
212222
__contains__(a, b)
213223

Lib/operator.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
This is the pure Python implementation of the module.
1111
"""
1212

13-
__all__ = ['abs', 'add', 'and_', 'attrgetter', 'call', 'concat', 'contains', 'countOf',
13+
__all__ = ['abs', 'add', 'and_', 'attrgetter', 'call', 'concat',
14+
'in_', 'not_in', 'contains', 'countOf',
1415
'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
1516
'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul',
1617
'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift',
@@ -150,10 +151,22 @@ def concat(a, b):
150151
raise TypeError(msg)
151152
return a + b
152153

154+
155+
def in_(a, b):
156+
"Same as a in b."
157+
return a in b
158+
159+
160+
def not_in(a, b):
161+
"Same as a not in b."
162+
return a not in b
163+
164+
153165
def contains(a, b):
154166
"Same as b in a (note reversed operands)."
155167
return b in a
156168

169+
157170
def countOf(a, b):
158171
"Return the number of items in a which are, or which equal, b."
159172
count = 0

Lib/test/test_operator.py

+16
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,22 @@ def test_rshift(self):
290290
self.assertEqual(operator.rshift(5, 0), 5)
291291
self.assertRaises(ValueError, operator.rshift, 2, -1)
292292

293+
def test_in(self):
294+
operator = self.module
295+
self.assertRaises(TypeError, operator.in_)
296+
self.assertRaises(TypeError, operator.in_, None, None)
297+
self.assertRaises(ZeroDivisionError, operator.in_, 1, BadIterable())
298+
self.assertTrue(operator.in_(2, range(4)))
299+
self.assertFalse(operator.in_(5, range(4)))
300+
301+
def test_not_in(self):
302+
operator = self.module
303+
self.assertRaises(TypeError, operator.not_in)
304+
self.assertRaises(TypeError, operator.not_in, None, None)
305+
self.assertRaises(ZeroDivisionError, operator.not_in, 1, BadIterable())
306+
self.assertFalse(operator.not_in(2, range(4)))
307+
self.assertTrue(operator.not_in(5, range(4)))
308+
293309
def test_contains(self):
294310
operator = self.module
295311
self.assertRaises(TypeError, operator.contains)

Modules/_operator.c

+40
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,44 @@ _operator_iconcat_impl(PyObject *module, PyObject *a, PyObject *b)
474474
return PySequence_InPlaceConcat(a, b);
475475
}
476476

477+
/*[clinic input]
478+
_operator.in_ -> bool
479+
480+
a: object
481+
b: object
482+
/
483+
484+
Same as a in b.
485+
[clinic start generated code]*/
486+
487+
static int
488+
_operator_in__impl(PyObject *module, PyObject *a, PyObject *b)
489+
/*[clinic end generated code: output=cd4eca456096fa9a input=8bd20ace23fe9808]*/
490+
{
491+
return PySequence_Contains(b, a);
492+
}
493+
494+
/*[clinic input]
495+
_operator.not_in -> bool
496+
497+
a: object
498+
b: object
499+
/
500+
501+
Same as a not in b.
502+
[clinic start generated code]*/
503+
504+
static int
505+
_operator_not_in_impl(PyObject *module, PyObject *a, PyObject *b)
506+
/*[clinic end generated code: output=93a4db26908835bd input=203499d558a29ee3]*/
507+
{
508+
int result = PySequence_Contains(b, a);
509+
if (result != -1) {
510+
result = 1 - result;
511+
}
512+
return result;
513+
}
514+
477515
/*[clinic input]
478516
_operator.contains -> bool
479517
@@ -910,6 +948,8 @@ _operator_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
910948
static struct PyMethodDef operator_methods[] = {
911949

912950
_OPERATOR_TRUTH_METHODDEF
951+
_OPERATOR_IN__METHODDEF
952+
_OPERATOR_NOT_IN_METHODDEF
913953
_OPERATOR_CONTAINS_METHODDEF
914954
_OPERATOR_INDEXOF_METHODDEF
915955
_OPERATOR_COUNTOF_METHODDEF

Modules/clinic/_operator.c.h

+71-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)