summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2015-08-17 02:43:34 (GMT)
committerRaymond Hettinger <python@rcn.com>2015-08-17 02:43:34 (GMT)
commit47d159f5220918f9c1216ba93583f3aa740a8944 (patch)
tree1e324fa8f68399c96643d09e0168b45f9be2a654
parent755cb0ae8d02daa7f231da90c303ebf9a0f3b01f (diff)
downloadcpython-47d159f5220918f9c1216ba93583f3aa740a8944.zip
cpython-47d159f5220918f9c1216ba93583f3aa740a8944.tar.gz
cpython-47d159f5220918f9c1216ba93583f3aa740a8944.tar.bz2
Issue #24379: Add operator.subscript() as a convenience for building slices.
-rw-r--r--Doc/library/operator.rst15
-rw-r--r--Doc/whatsnew/3.6.rst7
-rw-r--r--Lib/operator.py28
-rw-r--r--Lib/test/test_operator.py33
4 files changed, 81 insertions, 2 deletions
diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst
index c01e63b..0695391 100644
--- a/Doc/library/operator.rst
+++ b/Doc/library/operator.rst
@@ -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
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index e2aa1e2..48ff38a 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -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
diff --git a/Lib/operator.py b/Lib/operator.py
index 0e2e53e..bc2a947 100644
--- a/Lib/operator.py
+++ b/Lib/operator.py
@@ -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:
diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py
index 54fd1f4..27501c2 100644
--- a/Lib/test/test_operator.py
+++ b/Lib/test/test_operator.py
@@ -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()