[Python-checkins] commit of r41844 - in python/trunk: Doc/lib/liboperator.tex Lib/test/test_operator.py Modules/operator.c

armin.rigo python-checkins at python.org
Thu Dec 29 17:50:50 CET 2005


Author: armin.rigo
Date: Thu Dec 29 17:50:42 2005
New Revision: 41844

Modified:
   python/trunk/Doc/lib/liboperator.tex
   python/trunk/Lib/test/test_operator.py
   python/trunk/Modules/operator.c
Log:
adding in-place operators to the operator module.


Modified: python/trunk/Doc/lib/liboperator.tex
==============================================================================
--- python/trunk/Doc/lib/liboperator.tex	(original)
+++ python/trunk/Doc/lib/liboperator.tex	Thu Dec 29 17:50:42 2005
@@ -237,6 +237,108 @@
 \end{funcdesc}
 
 
+Many operations have an ``in-place'' version.  The following functions
+provide a more primitive access to in-place operators than the usual
+syntax does; for example, the statement \code{x += y} is equivalent to
+\code{x = operator.iadd(x, y)}.  Another way to put it is to say that
+\code{z = operator.iadd(x, y)} is equivalent to the compound statement
+\code{z = x; z += y}.
+
+\begin{funcdesc}{iadd}{a, b}
+\funcline{__iadd__}{a, b}
+\code{a = iadd(a, b)} is equivalent to \code{a += b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{iand}{a, b}
+\funcline{__iand__}{a, b}
+\code{a = iand(a, b)} is equivalent to \code{a \&= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{iconcat}{a, b}
+\funcline{__iconcat__}{a, b}
+\code{a = iconcat(a, b)} is equivalent to \code{a += b} for \var{a}
+and \var{b} sequences.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{idiv}{a, b}
+\funcline{__idiv__}{a, b}
+\code{a = idiv(a, b)} is equivalent to \code{a /= b} when
+\code{__future__.division} is not in effect.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{ifloordiv}{a, b}
+\funcline{__ifloordiv__}{a, b}
+\code{a = ifloordiv(a, b)} is equivalent to \code{a //= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{ilshift}{a, b}
+\funcline{__ilshift__}{a, b}
+\code{a = ilshift(a, b)} is equivalent to \code{a <}\code{<= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{imod}{a, b}
+\funcline{__imod__}{a, b}
+\code{a = imod(a, b)} is equivalent to \code{a \%= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{imul}{a, b}
+\funcline{__imul__}{a, b}
+\code{a = imul(a, b)} is equivalent to \code{a *= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{ior}{a, b}
+\funcline{__ior__}{a, b}
+\code{a = ior(a, b)} is equivalent to \code{a |= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{ipow}{a, b}
+\funcline{__ipow__}{a, b}
+\code{a = ipow(a, b)} is equivalent to \code{a **= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{irepeat}{a, b}
+\funcline{__irepeat__}{a, b}
+\code{a = irepeat(a, b)} is equivalent to \code{a *= b} where
+\var{a} is a sequence and \var{b} is an integer.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{irshift}{a, b}
+\funcline{__irshift__}{a, b}
+\code{a = irshift(a, b)} is equivalent to \code{a >}\code{>= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{isub}{a, b}
+\funcline{__isub__}{a, b}
+\code{a = isub(a, b)} is equivalent to \code{a -= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{itruediv}{a, b}
+\funcline{__itruediv__}{a, b}
+\code{a = itruediv(a, b)} is equivalent to \code{a /= b} when
+\code{__future__.division} is in effect.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{ixor}{a, b}
+\funcline{__ixor__}{a, b}
+\code{a = ixor(a, b)} is equivalent to \code{a \textasciicircum= b}.
+\versionadded{2.5}
+\end{funcdesc}
+
+
 The \module{operator} module also defines a few predicates to test the
 type of objects.  \note{Be careful not to misinterpret the
 results of these functions; only \function{isCallable()} has any

Modified: python/trunk/Lib/test/test_operator.py
==============================================================================
--- python/trunk/Lib/test/test_operator.py	(original)
+++ python/trunk/Lib/test/test_operator.py	Thu Dec 29 17:50:42 2005
@@ -412,6 +412,53 @@
         self.assertEqual(operator.itemgetter(2,10,5)(data), ('2', '10', '5'))
         self.assertRaises(TypeError, operator.itemgetter(2, 'x', 5), data)
 
+    def test_inplace(self):
+        class C(object):
+            def __iadd__     (self, other): return "iadd"
+            def __iand__     (self, other): return "iand"
+            def __idiv__     (self, other): return "idiv"
+            def __ifloordiv__(self, other): return "ifloordiv"
+            def __ilshift__  (self, other): return "ilshift"
+            def __imod__     (self, other): return "imod"
+            def __imul__     (self, other): return "imul"
+            def __ior__      (self, other): return "ior"
+            def __ipow__     (self, other): return "ipow"
+            def __irshift__  (self, other): return "irshift"
+            def __isub__     (self, other): return "isub"
+            def __itruediv__ (self, other): return "itruediv"
+            def __ixor__     (self, other): return "ixor"
+            def __getitem__(self, other): return 5  # so that C is a sequence
+        c = C()
+        self.assertEqual(operator.iadd     (c, 5), "iadd")
+        self.assertEqual(operator.iand     (c, 5), "iand")
+        self.assertEqual(operator.idiv     (c, 5), "idiv")
+        self.assertEqual(operator.ifloordiv(c, 5), "ifloordiv")
+        self.assertEqual(operator.ilshift  (c, 5), "ilshift")
+        self.assertEqual(operator.imod     (c, 5), "imod")
+        self.assertEqual(operator.imul     (c, 5), "imul")
+        self.assertEqual(operator.ior      (c, 5), "ior")
+        self.assertEqual(operator.ipow     (c, 5), "ipow")
+        self.assertEqual(operator.irshift  (c, 5), "irshift")
+        self.assertEqual(operator.isub     (c, 5), "isub")
+        self.assertEqual(operator.itruediv (c, 5), "itruediv")
+        self.assertEqual(operator.ixor     (c, 5), "ixor")
+        self.assertEqual(operator.iconcat  (c, c), "iadd")
+        self.assertEqual(operator.irepeat  (c, 5), "imul")
+        self.assertEqual(operator.__iadd__     (c, 5), "iadd")
+        self.assertEqual(operator.__iand__     (c, 5), "iand")
+        self.assertEqual(operator.__idiv__     (c, 5), "idiv")
+        self.assertEqual(operator.__ifloordiv__(c, 5), "ifloordiv")
+        self.assertEqual(operator.__ilshift__  (c, 5), "ilshift")
+        self.assertEqual(operator.__imod__     (c, 5), "imod")
+        self.assertEqual(operator.__imul__     (c, 5), "imul")
+        self.assertEqual(operator.__ior__      (c, 5), "ior")
+        self.assertEqual(operator.__ipow__     (c, 5), "ipow")
+        self.assertEqual(operator.__irshift__  (c, 5), "irshift")
+        self.assertEqual(operator.__isub__     (c, 5), "isub")
+        self.assertEqual(operator.__itruediv__ (c, 5), "itruediv")
+        self.assertEqual(operator.__ixor__     (c, 5), "ixor")
+        self.assertEqual(operator.__iconcat__  (c, c), "iadd")
+        self.assertEqual(operator.__irepeat__  (c, 5), "imul")
 
 def test_main(verbose=None):
     import sys

Modified: python/trunk/Modules/operator.c
==============================================================================
--- python/trunk/Modules/operator.c	(original)
+++ python/trunk/Modules/operator.c	Thu Dec 29 17:50:42 2005
@@ -80,9 +80,23 @@
 spam2(op_and_          , PyNumber_And)
 spam2(op_xor           , PyNumber_Xor)
 spam2(op_or_           , PyNumber_Or)
+spam2(op_iadd          , PyNumber_InPlaceAdd)
+spam2(op_isub          , PyNumber_InPlaceSubtract)
+spam2(op_imul          , PyNumber_InPlaceMultiply)
+spam2(op_idiv          , PyNumber_InPlaceDivide)
+spam2(op_ifloordiv     , PyNumber_InPlaceFloorDivide)
+spam2(op_itruediv      , PyNumber_InPlaceTrueDivide)
+spam2(op_imod          , PyNumber_InPlaceRemainder)
+spam2(op_ilshift       , PyNumber_InPlaceLshift)
+spam2(op_irshift       , PyNumber_InPlaceRshift)
+spam2(op_iand          , PyNumber_InPlaceAnd)
+spam2(op_ixor          , PyNumber_InPlaceXor)
+spam2(op_ior           , PyNumber_InPlaceOr)
 spami(isSequenceType   , PySequence_Check)
 spam2(op_concat        , PySequence_Concat)
 spamoi(op_repeat       , PySequence_Repeat)
+spam2(op_iconcat       , PySequence_InPlaceConcat)
+spamoi(op_irepeat      , PySequence_InPlaceRepeat)
 spami2b(op_contains     , PySequence_Contains)
 spami2b(sequenceIncludes, PySequence_Contains)
 spami2(indexOf         , PySequence_Index)
@@ -108,6 +122,15 @@
 }
 
 static PyObject*
+op_ipow(PyObject *s, PyObject *a)
+{
+	PyObject *a1, *a2;
+	if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))
+		return PyNumber_InPlacePower(a1, a2, Py_None);
+	return NULL;
+}
+
+static PyObject*
 is_(PyObject *s, PyObject *a)
 {
 	PyObject *a1, *a2, *result = NULL;
@@ -224,17 +247,34 @@
 spam2(and_,__and__, "and_(a, b) -- Same as a & b.")
 spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")
 spam2(or_,__or__, "or_(a, b) -- Same as a | b.")
+spam2(iadd,__iadd__, "iadd(a, b) -- Same as a += b.")
+spam2(isub,__isub__, "isub(a, b) -- Same as a -= b.")
+spam2(imul,__imul__, "imul(a, b) -- Same as a *= b.")
+spam2(idiv,__idiv__, "idiv(a, b) -- Same as a /= b when __future__.division is not in effect.")
+spam2(ifloordiv,__ifloordiv__, "ifloordiv(a, b) -- Same as a //= b.")
+spam2(itruediv,__itruediv__, "itruediv(a, b) -- Same as a /= b when __future__.division is in effect.")
+spam2(imod,__imod__, "imod(a, b) -- Same as a %= b.")
+spam2(ilshift,__ilshift__, "ilshift(a, b) -- Same as a <<= b.")
+spam2(irshift,__irshift__, "irshift(a, b) -- Same as a >>= b.")
+spam2(iand,__iand__, "iand(a, b) -- Same as a &= b.")
+spam2(ixor,__ixor__, "ixor(a, b) -- Same as a ^= b.")
+spam2(ior,__ior__, "ior(a, b) -- Same as a |= b.")
 spam2(concat,__concat__,
  "concat(a, b) -- Same as a + b, for a and b sequences.")
 spam2(repeat,__repeat__,
  "repeat(a, b) -- Return a * b, where a is a sequence, and b is an integer.")
+spam2(iconcat,__iconcat__,
+ "iconcat(a, b) -- Same as a += b, for a and b sequences.")
+spam2(irepeat,__irepeat__,
+ "irepeat(a, b) -- Same as a *= b, where a is a sequence, and b is an integer.")
 spam2(getitem,__getitem__,
  "getitem(a, b) -- Same as a[b].")
 spam2(setitem,__setitem__,
  "setitem(a, b, c) -- Same as a[b] = c.")
 spam2(delitem,__delitem__,
  "delitem(a, b) -- Same as del a[b].")
-spam2(pow,__pow__, "pow(a, b) -- Same as a**b.")
+spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")
+spam2(ipow,__ipow__, "ipow(a, b) -- Same as a **= b.")
 spam2(getslice,__getslice__,
  "getslice(a, b, c) -- Same as a[b:c].")
 spam2(setslice,__setslice__,


More information about the Python-checkins mailing list