diff --git a/Doc/lib/liboperator.tex b/Doc/lib/liboperator.tex index f3f09809b4c..7bd66ea722e 100644 --- a/Doc/lib/liboperator.tex +++ b/Doc/lib/liboperator.tex @@ -48,7 +48,7 @@ for more informations about rich comparisons. The logical operations are also generally applicable to all objects, -and support truth tests and Boolean operations: +and support truth tests, identity tests, and Boolean operations: \begin{funcdesc}{not_}{o} \funcline{__not__}{o} @@ -64,6 +64,14 @@ otherwise. This is equivalent to using the \class{bool} constructor. \end{funcdesc} +\begin{funcdesc}{is_}{a, b} +Return \code{\var{a} is \var{b}}. Tests object identity. +\end{funcdesc} + +\begin{funcdesc}{is_not}{a, b} +Return \code{\var{a} is not \var{b}}. Tests object identity. +\end{funcdesc} + The mathematical and bitwise operations are the most numerous: diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py index 611e4277ff3..422a3cb74aa 100644 --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -215,6 +215,17 @@ class OperatorTestCase(unittest.TestCase): def test_bitwise_xor(self): self.failUnless(operator.xor(0xb, 0xc) == 0x7) + def test_is(self): + a = b = 'xyzpdq' + c = a[:3] + b[3:] + self.failUnless(operator.is_(a, b)) + self.failIf(operator.is_(a,c)) + + def test_is_not(self): + a = b = 'xyzpdq' + c = a[:3] + b[3:] + self.failIf(operator.is_not(a, b)) + self.failUnless(operator.is_not(a,c)) def test_main(): test_support.run_unittest(OperatorTestCase) diff --git a/Misc/NEWS b/Misc/NEWS index 30b49022ca8..349712fb2cc 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -517,6 +517,11 @@ Core and builtins Extension modules ----------------- +- Added three operators to the operator module: + operator.pow(a,b) which is equivalent to: a**b. + operator.is_(a,b) which is equivalent to: a is b. + operator.is_not(a,b) which is equivalent to: a is not b. + - posix.openpty now works on all systems that have /dev/ptmx. - A module zipimport exists to support importing code from zip @@ -733,8 +738,6 @@ Library or when you need to use sets as dict keys, and a class BaseSet which is the base class of the two. -- Added operator.pow(a,b) which is equivalent to a**b. - - Added random.sample(population,k) for random sampling without replacement. Returns a k length list of unique elements chosen from the population. diff --git a/Modules/operator.c b/Modules/operator.c index 5371b95a1cb..7638fb80a13 100644 --- a/Modules/operator.c +++ b/Modules/operator.c @@ -107,6 +107,28 @@ op_pow(PyObject *s, PyObject *a) return NULL; } +static PyObject* +is_(PyObject *s, PyObject *a) +{ + PyObject *a1, *a2, *result = NULL; + if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) { + result = (a1 == a2) ? Py_True : Py_False; + Py_INCREF(result); + } + return result; +} + +static PyObject* +is_not(PyObject *s, PyObject *a) +{ + PyObject *a1, *a2, *result = NULL; + if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) { + result = (a1 != a2) ? Py_True : Py_False; + Py_INCREF(result); + } + return result; +} + static PyObject* op_getslice(PyObject *s, PyObject *a) { @@ -182,6 +204,8 @@ spam1(countOf, spam1o(isMappingType, "isMappingType(a) -- Return True if a has a mapping type, False otherwise.") +spam1(is_, "is_(a, b) -- Same as a is b.") +spam1(is_not, "is_not(a, b) -- Same as a is not b.") spam2(add,__add__, "add(a, b) -- Same as a + b.") spam2(sub,__sub__, "sub(a, b) -- Same as a - b.") spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")