Micropython 用户模块:Class 打印初始化数据,即使属性已更改

Micropython User Module: Class Prints Initialized Data Even If Attributes Have Changed

这是前端问题的直观表示。请注意,即使属性发生变化,打印 class 的输出也不会改变,但我通过直接打印属性获得了正确的值。

import bitbanglab as bbl

class Entity(bbl.Entity):
    def __init__(self):
        super().__init__(bytearray([0x0F]), 1, 1, 2, 2, 8, 2)
        print(self) #Entity(x:1, y:1, width:2, height:2, scale:8, len:1, pal:2)
        self.x = 50
        self.y = 20
        self.width = 50
        self.height= 60
        self.scale = 10
        self.len = 200
        self.pal = 14
        print(self) #Entity(x:1, y:1, width:2, height:2, scale:8, len:1, pal:2)
        print(self.x) #50
        print(self.y) #20
        
Entity()

打印方式

STATIC void Entity_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
    (void)kind;
    bitbanglab_Entity_obj_t *self = MP_OBJ_TO_PTR(self_in);
    mp_printf(print, "Entity(x:%u, y:%u, width:%u, height:%u, scale:%u, len:%u, pal:%u)", self->x, self->y, self->width, self->height, self->scale, self->len, self->pal);
}

get/set属性

STATIC void Entity_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
    bitbanglab_Entity_obj_t *self = MP_OBJ_TO_PTR(self_in);
    if (dest[0] == MP_OBJ_NULL) {
        if (attr == MP_QSTR_x)
            dest[0] = mp_obj_new_int(self->x);
        else if(attr == MP_QSTR_y)
            dest[0] = mp_obj_new_int(self->y);
        else if(attr == MP_QSTR_width)
            dest[0] = mp_obj_new_int(self->width);
        else if(attr == MP_QSTR_height)
            dest[0] = mp_obj_new_int(self->height);
        else if(attr == MP_QSTR_scale)
            dest[0] = mp_obj_new_int(self->scale);
        else if(attr == MP_QSTR_len)
            dest[0] = mp_obj_new_int(self->len);
        else if(attr == MP_QSTR_pal)
            dest[0] = mp_obj_new_int(self->pal);
    } else {
        if (attr == MP_QSTR_x)
            self->x      = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_y)
            self->y      = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_width)
            self->width  = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_height) 
            self->height = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_scale) 
            self->scale  = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_len) 
            self->len    = mp_obj_get_int(dest[1]);
        else if (attr == MP_QSTR_pal)
            self->pal    = mp_obj_get_int(dest[1]);
        dest[0] = MP_OBJ_NULL;
    }
}

Class类型

const mp_obj_type_t bitbanglab_Entity_type = {
    { &mp_type_type },
    .name        = MP_QSTR_bitbanglab,
    .print       = Entity_print,
    .make_new    = Entity_make_new,
    .locals_dict = (mp_obj_dict_t*)&Entity_locals_dict,
    .attr        = Entity_attr,
};

Class 对象

typedef struct _bitbanglab_Entity_obj_t {
    mp_obj_base_t base;
    uint8_t *bitmap;
    uint16_t len;
    uint16_t x;
    uint16_t y;
    uint16_t width;
    uint16_t height;
    uint8_t  scale;
    uint8_t  pal;
} bitbanglab_Entity_obj_t;

Class

class 还没有任何方法。 locals_dict_table 为空。

mp_obj_t Entity_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
    mp_arg_check_num(n_args, n_kw, 7, 7, true);
    
    //make self
    bitbanglab_Entity_obj_t *self = m_new_obj(bitbanglab_Entity_obj_t);
    self->base.type = &bitbanglab_Entity_type;
    
    //arguments
    enum { ARG_bitmap, ARG_x, ARG_y, ARG_width, ARG_height, ARG_scale, ARG_pal};
    
    //get buffer
    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(args[ARG_bitmap], &bufinfo, MP_BUFFER_RW);
    
    //properties
    self->bitmap = (uint8_t *)bufinfo.buf;
    self->len    = bufinfo.len;
    self->x      = mp_obj_get_int(args[ARG_x]);
    self->y      = mp_obj_get_int(args[ARG_y]);
    self->width  = mp_obj_get_int(args[ARG_width]);
    self->height = mp_obj_get_int(args[ARG_height]);
    self->scale  = mp_obj_get_int(args[ARG_scale]);
    self->pal    = mp_obj_get_int(args[ARG_pal]);
    
    return MP_OBJ_FROM_PTR(self);
}

我意识到了这个问题。我正在子class我的用户模块定义 class,我设置的值不是 super 上的值。如果我在没有子 class 的情况下实例化 Entity class 并更改属性,则打印 class 会反映这些更改。现在我的新问题是弄清楚如何从 subclass 获取 super 的属性。当我全部弄清楚后,我会更新这个答案以使其更强大。