@@ -2222,31 +2222,56 @@ typedef struct {
22222222
22232223static PyType_Spec defdict_spec ;
22242224
2225- PyDoc_STRVAR (defdict_missing_doc ,
2226- "__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\
2227- if self.default_factory is None: raise KeyError((key,))\n\
2228- self[key] = value = self.default_factory()\n\
2229- return value\n\
2225+ PyDoc_STRVAR (defdict_getitem_doc ,
2226+ "__getitem__($self, key, /)\n--\n\n\
2227+ Return self[key]. If the item doesn't exist, it is automatically created.\n\
2228+ The value is generated by calling either the __missing__ method (if it exists)\n\
2229+ or the default_factory attribute (if it isn't None). If neither can be called,\n\
2230+ a KeyError is raised.\
22302231" );
22312232
22322233static PyObject *
2233- defdict_missing (PyObject * op , PyObject * key )
2234+ defdict_subscript (PyObject * op , PyObject * key )
22342235{
2235- defdictobject * dd = defdictobject_CAST (op );
2236- PyObject * factory = dd -> default_factory ;
2236+ PyDictObject * mp = (PyDictObject * )op ;
2237+ Py_ssize_t ix ;
2238+ Py_hash_t hash ;
22372239 PyObject * value ;
2238- if (factory == NULL || factory == Py_None ) {
2239- /* XXX Call dict.__missing__(key) */
2240- _PyErr_SetKeyError (key );
2240+
2241+ hash = _PyObject_HashFast (key );
2242+ if (hash == -1 ) {
2243+ _Py_dict_unhashable_type (op , key );
22412244 return NULL ;
22422245 }
2243- value = _PyObject_CallNoArgs (factory );
2244- if (value == NULL )
2245- return value ;
2246- if (PyObject_SetItem (op , key , value ) < 0 ) {
2247- Py_DECREF (value );
2248- return NULL ;
2246+ Py_BEGIN_CRITICAL_SECTION (op );
2247+ ix = _Py_dict_lookup (mp , key , hash , & value );
2248+ if (value != NULL ) {
2249+ Py_INCREF (value );
2250+ } else if (ix != DKIX_ERROR ) {
2251+ /* Try to call self.__missing__(key) */
2252+ PyObject * missing ;
2253+ int ret = PyObject_GetOptionalAttr (op , & _Py_ID (__missing__ ), & missing );
2254+ if (ret == 1 ) {
2255+ value = PyObject_CallOneArg (missing , key );
2256+ Py_DECREF (missing );
2257+ } else if (ret == 0 ) {
2258+ /* Try to call self.default_factory() */
2259+ PyObject * factory = defdictobject_CAST (op )-> default_factory ;
2260+ if (factory != NULL && factory != Py_None ) {
2261+ value = _PyObject_CallNoArgs (factory );
2262+ } else {
2263+ _PyErr_SetKeyError (key );
2264+ }
2265+ }
2266+ /* Try to insert the new value in the dict */
2267+ if (value != NULL ) {
2268+ ret = _PyDict_SetItem_KnownHash_LockHeld (mp , Py_NewRef (key ),
2269+ Py_NewRef (value ), hash );
2270+ if (ret < 0 )
2271+ value = NULL ;
2272+ }
22492273 }
2274+ Py_END_CRITICAL_SECTION ();
22502275 return value ;
22512276}
22522277
@@ -2327,8 +2352,8 @@ defdict_reduce(PyObject *op, PyObject *Py_UNUSED(dummy))
23272352}
23282353
23292354static PyMethodDef defdict_methods [] = {
2330- {"__missing__ " , defdict_missing , METH_O ,
2331- defdict_missing_doc },
2355+ {"__getitem__ " , defdict_subscript , METH_O | METH_COEXIST ,
2356+ defdict_getitem_doc },
23322357 {"copy" , defdict_copy , METH_NOARGS ,
23332358 defdict_copy_doc },
23342359 {"__copy__" , defdict_copy , METH_NOARGS ,
@@ -2343,7 +2368,7 @@ static PyMethodDef defdict_methods[] = {
23432368static PyMemberDef defdict_members [] = {
23442369 {"default_factory" , _Py_T_OBJECT ,
23452370 offsetof(defdictobject , default_factory ), 0 ,
2346- PyDoc_STR ("Factory for default value called by __missing__ ()." )},
2371+ PyDoc_STR ("Factory for default value, called by __getitem__ ()." )},
23472372 {NULL }
23482373};
23492374
@@ -2507,6 +2532,7 @@ static PyType_Slot defdict_slots[] = {
25072532 {Py_tp_init , defdict_init },
25082533 {Py_tp_alloc , PyType_GenericAlloc },
25092534 {Py_tp_free , PyObject_GC_Del },
2535+ {Py_mp_subscript , defdict_subscript },
25102536 {0 , NULL },
25112537};
25122538
0 commit comments