Browse Source

py/objboundmeth: Support comparing and hashing bound methods.

This behaviour matches CPython.  It's useful to be able to store bound
method objects in dicts/sets, and compare for equality, eg when storing
them in a list and using list.remove().

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
pull/12639/head
Daniël van de Giessen 4 years ago
committed by Damien George
parent
commit
4f5e165d0b
  1. 1
      py/obj.h
  2. 25
      py/objboundmeth.c

1
py/obj.h

@ -828,6 +828,7 @@ extern const mp_obj_type_t mp_type_fun_bc;
extern const mp_obj_type_t mp_type_module; extern const mp_obj_type_t mp_type_module;
extern const mp_obj_type_t mp_type_staticmethod; extern const mp_obj_type_t mp_type_staticmethod;
extern const mp_obj_type_t mp_type_classmethod; extern const mp_obj_type_t mp_type_classmethod;
extern const mp_obj_type_t mp_type_bound_meth;
extern const mp_obj_type_t mp_type_property; extern const mp_obj_type_t mp_type_property;
extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_stringio;
extern const mp_obj_type_t mp_type_bytesio; extern const mp_obj_type_t mp_type_bytesio;

25
py/objboundmeth.c

@ -83,6 +83,25 @@ STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co
return mp_call_method_self_n_kw(self->meth, self->self, n_args, n_kw, args); return mp_call_method_self_n_kw(self->meth, self->self, n_args, n_kw, args);
} }
STATIC mp_obj_t bound_meth_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_HASH:
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self->self ^ (mp_uint_t)self->meth);
default:
return MP_OBJ_NULL; // op not supported
}
}
STATIC mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (!mp_obj_is_type(rhs_in, &mp_type_bound_meth) || op != MP_BINARY_OP_EQUAL) {
return MP_OBJ_NULL; // op not supported
}
mp_obj_bound_meth_t *lhs = MP_OBJ_TO_PTR(lhs_in);
mp_obj_bound_meth_t *rhs = MP_OBJ_TO_PTR(rhs_in);
return mp_obj_new_bool(lhs->self == rhs->self && lhs->meth == rhs->meth);
}
#if MICROPY_PY_FUNCTION_ATTRS #if MICROPY_PY_FUNCTION_ATTRS
STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] != MP_OBJ_NULL) { if (dest[0] != MP_OBJ_NULL) {
@ -107,13 +126,15 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
#define BOUND_METH_TYPE_ATTR #define BOUND_METH_TYPE_ATTR
#endif #endif
STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE(
mp_type_bound_meth, mp_type_bound_meth,
MP_QSTR_bound_method, MP_QSTR_bound_method,
MP_TYPE_FLAG_NONE, MP_TYPE_FLAG_NONE,
BOUND_METH_TYPE_PRINT BOUND_METH_TYPE_PRINT
BOUND_METH_TYPE_ATTR BOUND_METH_TYPE_ATTR
call, bound_meth_call call, bound_meth_call,
unary_op, bound_meth_unary_op,
binary_op, bound_meth_binary_op
); );
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {

Loading…
Cancel
Save