diff --git a/py/objtype.c b/py/objtype.c index db99d407acfcd5b6c176abe1184f101a5a0c8615..ca52006f25a299b0ca8c03b5b605d375e24f7ff7 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -472,7 +472,22 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des dest[0] = elem->value; return; } - +#if MICROPY_CPYTHON_COMPAT + if (attr == MP_QSTR___dict__) { + // Create a new dict with a copy of the instance's map items. + // This creates, unlike CPython, a 'read-only' __dict__: modifying + // it will not result in modifications to the actual instance members. + mp_map_t *map = &self->members; + mp_obj_t attr_dict = mp_obj_new_dict(map->used); + for (mp_uint_t i = 0; i < map->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value); + } + } + dest[0] = attr_dict; + return; + } +#endif struct class_lookup_data lookup = { .obj = self, .attr = attr, diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 3be6168a8f22ca1f2d9d4ef2eca1a3853b4fb1a1..496896dad45169efc1caaad047779cc22bd1a1ba 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -46,6 +46,7 @@ Q(__locals__) Q(__main__) Q(__module__) Q(__name__) +Q(__dict__) Q(__hash__) Q(__next__) Q(__qualname__) diff --git a/tests/basics/builtin_dict.py b/tests/basics/builtin_dict.py new file mode 100644 index 0000000000000000000000000000000000000000..f51ec21d007ae7b3b076dec8376bd10dab2713a3 --- /dev/null +++ b/tests/basics/builtin_dict.py @@ -0,0 +1,11 @@ +class A: + def __init__(self): + self.a=1 + self.b=2 + +try: + d=A().__dict__ + print(d['a']) + print(d['b']) +except AttributeError: + print("SKIP")