diff -r 4c1d543135ef Doc/library/re.rst --- a/Doc/library/re.rst Thu Jul 31 23:58:27 2014 -0500 +++ b/Doc/library/re.rst Fri Aug 01 14:57:03 2014 +0300 @@ -873,6 +873,15 @@ if match: process(match) +Match objects are iterable and can be unpacked. ``iter(match)`` is equivalent +to ``iter(match.groups())``. For example: + + >>> [(k, v) for k, v in re.finditer(r"(\w+):?(\w+)?", "ab:cd, ef")] + [('ab', 'cd'), ('ef', None)] + +.. versionadded:: 3.5 + Match objects are now iterable. + Match objects support the following methods and attributes: diff -r 4c1d543135ef Lib/test/test_re.py --- a/Lib/test/test_re.py Thu Jul 31 23:58:27 2014 -0500 +++ b/Lib/test/test_re.py Fri Aug 01 14:57:03 2014 +0300 @@ -349,6 +349,18 @@ (None, 'b', None)) self.assertEqual(pat.match('ac').group(1, 'b2', 3), ('a', None, 'c')) + def test_re_match_iter(self): + pat = re.compile(r'(\w+):(\w+)?:(\w+)') + m = pat.match('ab::cd=') + it = iter(m) + self.assertEqual(next(it), 'ab') + self.assertEqual(next(it), None) + self.assertEqual(next(it), 'cd') + self.assertRaises(StopIteration, next, it) + self.assertEqual(list(m), ['ab', None, 'cd']) + x, y, z = m + self.assertEqual((x, y, z), ('ab', None, 'cd')) + def test_re_fullmatch(self): # Issue 16203: Proposal: add re.fullmatch() method. self.assertEqual(re.fullmatch(r"a", "a").span(), (0, 1)) @@ -896,6 +908,10 @@ self.assertEqual([item.group(0) for item in iter], ["::", "::"]) + iter = re.finditer(r"(\w+):?(\w+)?", "ab:cd\nef\n") + self.assertEqual([(k, v) for k, v in iter], + [('ab', 'cd'), ('ef', None)]) + def test_bug_926075(self): self.assertTrue(re.compile('bug_926075') is not re.compile(b'bug_926075')) diff -r 4c1d543135ef Modules/_sre.c --- a/Modules/_sre.c Thu Jul 31 23:58:27 2014 -0500 +++ b/Modules/_sre.c Fri Aug 01 14:57:03 2014 +0300 @@ -2080,6 +2080,31 @@ } static PyObject* +match_iter(MatchObject* self) +{ + PyObject *result, *iter; + Py_ssize_t index; + + result = PyTuple_New(self->groups-1); + if (!result) + return NULL; + + for (index = 1; index < self->groups; index++) { + PyObject* item; + item = match_getslice_by_index(self, index, Py_None); + if (!item) { + Py_DECREF(result); + return NULL; + } + PyTuple_SET_ITEM(result, index-1, item); + } + + iter = PyObject_GetIter(result); + Py_DECREF(result); + return iter; +} + +static PyObject* match_groups(MatchObject* self, PyObject* args, PyObject* kw) { PyObject* result; @@ -2478,7 +2503,7 @@ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ + (getiterfunc)match_iter, /* tp_iter */ 0, /* tp_iternext */ match_methods, /* tp_methods */ match_members, /* tp_members */