mirror of
https://github.com/python/cpython.git
synced 2025-08-01 23:53:15 +00:00
bpo-45045: Optimize mapping patterns of structural pattern matching (GH-28043)
This commit is contained in:
parent
94b2639fad
commit
e6497fe698
2 changed files with 30 additions and 6 deletions
|
@ -2641,6 +2641,19 @@ class TestPatma(unittest.TestCase):
|
||||||
self.assertEqual(f((False, range(-1, -11, -1), True)), alts[3])
|
self.assertEqual(f((False, range(-1, -11, -1), True)), alts[3])
|
||||||
self.assertEqual(f((False, range(10, 20), True)), alts[4])
|
self.assertEqual(f((False, range(10, 20), True)), alts[4])
|
||||||
|
|
||||||
|
def test_patma_248(self):
|
||||||
|
class C(dict):
|
||||||
|
@staticmethod
|
||||||
|
def get(key, default=None):
|
||||||
|
return 'bar'
|
||||||
|
|
||||||
|
x = C({'foo': 'bar'})
|
||||||
|
match x:
|
||||||
|
case {'foo': bar}:
|
||||||
|
y = bar
|
||||||
|
|
||||||
|
self.assertEqual(y, 'bar')
|
||||||
|
|
||||||
|
|
||||||
class TestSyntaxErrors(unittest.TestCase):
|
class TestSyntaxErrors(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -841,12 +841,18 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
|
||||||
PyObject *seen = NULL;
|
PyObject *seen = NULL;
|
||||||
PyObject *dummy = NULL;
|
PyObject *dummy = NULL;
|
||||||
PyObject *values = NULL;
|
PyObject *values = NULL;
|
||||||
|
PyObject *get_name = NULL;
|
||||||
|
PyObject *get = NULL;
|
||||||
// We use the two argument form of map.get(key, default) for two reasons:
|
// We use the two argument form of map.get(key, default) for two reasons:
|
||||||
// - Atomically check for a key and get its value without error handling.
|
// - Atomically check for a key and get its value without error handling.
|
||||||
// - Don't cause key creation or resizing in dict subclasses like
|
// - Don't cause key creation or resizing in dict subclasses like
|
||||||
// collections.defaultdict that define __missing__ (or similar).
|
// collections.defaultdict that define __missing__ (or similar).
|
||||||
_Py_IDENTIFIER(get);
|
_Py_IDENTIFIER(get);
|
||||||
PyObject *get = _PyObject_GetAttrId(map, &PyId_get);
|
get_name = _PyUnicode_FromId(&PyId_get); // borrowed
|
||||||
|
if (get_name == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int meth_found = _PyObject_GetMethod(map, get_name, &get);
|
||||||
if (get == NULL) {
|
if (get == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -859,7 +865,7 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
|
||||||
if (dummy == NULL) {
|
if (dummy == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
values = PyList_New(0);
|
values = PyTuple_New(nkeys);
|
||||||
if (values == NULL) {
|
if (values == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -873,7 +879,14 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
|
||||||
}
|
}
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
PyObject *value = PyObject_CallFunctionObjArgs(get, key, dummy, NULL);
|
PyObject *args[] = { map, key, dummy };
|
||||||
|
PyObject *value = NULL;
|
||||||
|
if (meth_found) {
|
||||||
|
value = PyObject_Vectorcall(get, args, 3, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = PyObject_Vectorcall(get, &args[1], 2, NULL);
|
||||||
|
}
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -886,10 +899,8 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
|
||||||
values = Py_None;
|
values = Py_None;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
PyList_Append(values, value);
|
PyTuple_SET_ITEM(values, i, value);
|
||||||
Py_DECREF(value);
|
|
||||||
}
|
}
|
||||||
Py_SETREF(values, PyList_AsTuple(values));
|
|
||||||
// Success:
|
// Success:
|
||||||
done:
|
done:
|
||||||
Py_DECREF(get);
|
Py_DECREF(get);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue