py: Use __hash__ method if a type defines it
This commit is contained in:
parent
d8474d3617
commit
e00eeaf4cd
28
py/obj.c
28
py/obj.c
@ -172,18 +172,26 @@ mp_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
return mp_obj_tuple_hash(o_in);
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) {
|
||||
return (mp_int_t)o_in;
|
||||
|
||||
// TODO hash class and instances
|
||||
// TODO delegate to __hash__ method if it exists
|
||||
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type"));
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"unhashable type: '%s'", mp_obj_get_type_str(o_in)));
|
||||
} else if (MP_OBJ_IS_OBJ(o_in)) {
|
||||
// if a valid __hash__ method exists, use it
|
||||
mp_obj_t hash_method[2];
|
||||
mp_load_method_maybe(o_in, MP_QSTR___hash__, hash_method);
|
||||
if (hash_method[0] != MP_OBJ_NULL) {
|
||||
mp_obj_t hash_val = mp_call_method_n_kw(0, 0, hash_method);
|
||||
if (MP_OBJ_IS_INT(hash_val)) {
|
||||
return mp_obj_int_get(hash_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO hash class and instances - in CPython by default user created classes' __hash__ resolves to their id
|
||||
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type"));
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"unhashable type: '%s'", mp_obj_get_type_str(o_in)));
|
||||
}
|
||||
}
|
||||
|
||||
// this function implements the '==' operator (and so the inverse of '!=')
|
||||
|
@ -39,6 +39,7 @@ Q(__locals__)
|
||||
Q(__main__)
|
||||
Q(__module__)
|
||||
Q(__name__)
|
||||
Q(__hash__)
|
||||
Q(__next__)
|
||||
Q(__qualname__)
|
||||
Q(__path__)
|
||||
|
Loading…
x
Reference in New Issue
Block a user