]> granicus.if.org Git - python/commitdiff
Issue #24379: Add operator.subscript() as a convenience for building slices.
authorRaymond Hettinger <python@rcn.com>
Mon, 17 Aug 2015 02:43:34 +0000 (19:43 -0700)
committerRaymond Hettinger <python@rcn.com>
Mon, 17 Aug 2015 02:43:34 +0000 (19:43 -0700)
Doc/library/operator.rst
Doc/whatsnew/3.6.rst
Lib/operator.py
Lib/test/test_operator.py

index c01e63b77a993382f6e820956321d4f49f997812..06953917e78dace8e299e4e28bc96941d34c4377 100644 (file)
@@ -333,6 +333,21 @@ expect a function argument.
       [('orange', 1), ('banana', 2), ('apple', 3), ('pear', 5)]
 
 
+.. data:: subscript
+
+    A helper to turn subscript notation into indexing objects.  This can be
+    used to create item access patterns ahead of time to pass them into
+    various subscriptable objects.
+
+    For example:
+
+    * ``subscript[5] == 5``
+    * ``subscript[3:7:2] == slice(3, 7, 2)``
+    * ``subscript[5, 8] == (5, 8)``
+
+    .. versionadded:: 3.6
+
+
 .. function:: methodcaller(name[, args...])
 
    Return a callable object that calls the method *name* on its operand.  If
index e2aa1e2f02c5d67012cd490d0997ed5dc9b09c1a..48ff38a241fca2167f66d4c9153517a14157536a 100644 (file)
@@ -95,7 +95,12 @@ New Modules
 Improved Modules
 ================
 
-* None yet.
+operator
+--------
+
+* New object :data:`operator.subscript` makes it easier to create complex
+  indexers. For example: ``subscript[0:10:2] == slice(0, 10, 2)``
+  (Contributed by Joe Jevnik in :issue:`24379`.)
 
 
 Optimizations
index 0e2e53efc69a77dca0081ad67e2deb0accb9a288..bc2a9478b8ba3d97bce57c851c5f65eded6eabcb 100644 (file)
@@ -17,7 +17,7 @@ __all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
            'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
            'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod',
            'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift',
-           'setitem', 'sub', 'truediv', 'truth', 'xor']
+           'setitem', 'sub', 'subscript', 'truediv', 'truth', 'xor']
 
 from builtins import abs as _abs
 
@@ -408,6 +408,32 @@ def ixor(a, b):
     return a
 
 
+@object.__new__  # create a singleton instance
+class subscript:
+    """
+    A helper to turn subscript notation into indexing objects.  This can be
+    used to create item access patterns ahead of time to pass them into
+    various subscriptable objects.
+
+    For example:
+    subscript[5] == 5
+    subscript[3:7:2] == slice(3, 7, 2)
+    subscript[5, 8] == (5, 8)
+    """
+    __slots__ = ()
+
+    def __new__(cls):
+        raise TypeError("cannot create '{}' instances".format(cls.__name__))
+
+    @staticmethod
+    def __getitem__(key):
+        return key
+
+    @staticmethod
+    def __reduce__():
+        return 'subscript'
+
+
 try:
     from _operator import *
 except ImportError:
index 54fd1f4e528402a9783206131c8b7169044e85c1..27501c246698bc41b65861aebee10f1b548ba433 100644 (file)
@@ -596,5 +596,38 @@ class CCOperatorPickleTestCase(OperatorPickleTestCase, unittest.TestCase):
     module2 = c_operator
 
 
+class SubscriptTestCase:
+    def test_subscript(self):
+        subscript = self.module.subscript
+        self.assertIsNone(subscript[None])
+        self.assertEqual(subscript[0], 0)
+        self.assertEqual(subscript[0:1:2], slice(0, 1, 2))
+        self.assertEqual(
+            subscript[0, ..., :2, ...],
+            (0, Ellipsis, slice(2), Ellipsis),
+        )
+
+    def test_pickle(self):
+        from operator import subscript
+        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+            with self.subTest(proto=proto):
+                self.assertIs(
+                    pickle.loads(pickle.dumps(subscript, proto)),
+                    subscript,
+                )
+
+    def test_singleton(self):
+        with self.assertRaises(TypeError):
+            type(self.module.subscript)()
+
+    def test_immutable(self):
+        with self.assertRaises(AttributeError):
+            self.module.subscript.attr = None
+
+
+class PySubscriptTestCase(SubscriptTestCase, PyOperatorTestCase):
+    pass
+
+
 if __name__ == "__main__":
     unittest.main()