py: Support instance __call__ method.
This commit is contained in:
parent
410f30772f
commit
755565d2cb
11
py/objtype.c
11
py/objtype.c
@ -338,6 +338,16 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC mp_obj_t class_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||||
|
mp_obj_class_t *self = self_in;
|
||||||
|
mp_obj_t member = mp_obj_class_lookup(self->base.type, MP_QSTR___call__);
|
||||||
|
if (member == MP_OBJ_NULL) {
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
mp_obj_t meth = mp_obj_new_bound_meth(member, self);
|
||||||
|
return mp_call_function_n_kw(meth, n_args, n_kw, args);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
// type object
|
// type object
|
||||||
// - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
|
// - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
|
||||||
@ -474,6 +484,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
|||||||
o->load_attr = class_load_attr;
|
o->load_attr = class_load_attr;
|
||||||
o->store_attr = class_store_attr;
|
o->store_attr = class_store_attr;
|
||||||
o->subscr = class_subscr;
|
o->subscr = class_subscr;
|
||||||
|
o->call = class_call;
|
||||||
o->bases_tuple = bases_tuple;
|
o->bases_tuple = bases_tuple;
|
||||||
o->locals_dict = locals_dict;
|
o->locals_dict = locals_dict;
|
||||||
return o;
|
return o;
|
||||||
|
@ -31,6 +31,7 @@ Q(__repr__)
|
|||||||
Q(__str__)
|
Q(__str__)
|
||||||
Q(__getattr__)
|
Q(__getattr__)
|
||||||
Q(__del__)
|
Q(__del__)
|
||||||
|
Q(__call__)
|
||||||
|
|
||||||
Q(micropython)
|
Q(micropython)
|
||||||
Q(byte_code)
|
Q(byte_code)
|
||||||
|
@ -481,10 +481,13 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp
|
|||||||
|
|
||||||
// do the call
|
// do the call
|
||||||
if (type->call != NULL) {
|
if (type->call != NULL) {
|
||||||
return type->call(fun_in, n_args, n_kw, args);
|
mp_obj_t res = type->call(fun_in, n_args, n_kw, args);
|
||||||
} else {
|
if (res != NULL) {
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
|
// args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
|
||||||
|
18
tests/basics/class_call.py
Normal file
18
tests/basics/class_call.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
class C1:
|
||||||
|
def __call__(self, val):
|
||||||
|
print('call', val)
|
||||||
|
return 'item'
|
||||||
|
|
||||||
|
class C2:
|
||||||
|
|
||||||
|
def __getattr__(self, k):
|
||||||
|
pass
|
||||||
|
|
||||||
|
c1 = C1()
|
||||||
|
print(c1(1))
|
||||||
|
|
||||||
|
c2 = C2()
|
||||||
|
try:
|
||||||
|
print(c2(1))
|
||||||
|
except TypeError:
|
||||||
|
print("TypeError")
|
Loading…
Reference in New Issue
Block a user