diff -r bffb1b7a3293 Objects/dictobject.c --- a/Objects/dictobject.c Thu Dec 15 19:44:28 2016 +0900 +++ b/Objects/dictobject.c Thu Dec 15 20:03:30 2016 +0900 @@ -4296,10 +4296,23 @@ int } } else { - int shared = cached == ((PyDictObject *)dict)->ma_keys; + int was_shared = cached == ((PyDictObject *)dict)->ma_keys; res = PyDict_SetItem(dict, key, value); - if (shared && cached != ((PyDictObject *)dict)->ma_keys) { - /* Either update tp->ht_cached_keys or delete it */ + if (was_shared && cached != ((PyDictObject *)dict)->ma_keys) { + /* PyDict_SetItem() may call dictresize and convert split table + * into combined table. In such case, convert it to split + * table again and update type's shared key only when this is + * the only dict sharing key with the type. + * + * This is to allow using shared key in class like this: + * + * class C: + * def __init__(self): + * # one dict resize happens + * self.a, self.b, self.c = 1, 2, 3 + * self.d, self.e, self.f = 4, 5, 6 + * a = C() + */ if (cached->dk_refcnt == 1) { CACHED_KEYS(tp) = make_keys_shared(dict); }