microPython的源码解析之 objdict.c

本文深入解析MicroPython的objdict.c,介绍如何在有限资源下实现Python字典的核心功能,包括创建、操作和管理字典的方法。通过对MicroPython源码的解读,读者可以学习到Python解释器的实现逻辑,并了解到嵌入式Python环境下的字典操作流程。
摘要由CSDN通过智能技术生成

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.

microPython Python最小内核源码解析

#include <string.h>
#include <assert.h>

// 引入MicroPython运行时和对象类型定义
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/objtype.h"
#include "py/objstr.h"

/**
 * 判断一个对象是否为字典或有序字典
 * @param o 需要判断的MicroPython对象
 * @return 如果是字典或有序字典则返回true,否则返回false
 */
bool mp_obj_is_dict_or_ordereddict(mp_obj_t o) {
   
    return mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new;
}

// 定义一个空字典对象,用于初始化和作为默认值
const mp_obj_dict_t mp_const_empty_dict_obj = {
   
    .base = {
    .type = &mp_type_dict }, // 基础类型设置为字典类型
    .map = {
   
        .all_keys_are_qstrs = 0, // 所有键是否为qstr(快速字符串)类型
        .is_fixed = 1, // 是否固定,不可修改
        .is_ordered = 1, // 是否有序,保持插入顺序
        .used = 0, // 已使用的元素数量
        .alloc = 0, // 分配的元素数量
        .table = NULL // 字典存储的数组,初始为NULL
    }
};

// 字典更新函数,用于处理字典更新操作
static mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);

// 字典迭代器辅助函数,用于遍历字典中的元素
static mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {
   
    size_t max = dict->map.alloc; // 获取字典分配的槽位数量
    mp_map_t *map = &dict->map; // 获取字典的map结构体

    size_t i = *cur; // 当前迭代位置
    for (; i < max; i++) {
    // 遍历槽位
        if (mp_map_slot_is_filled(map, i)) {
    // 如果槽位被填充(即有元素)
            *cur = i + 1; // 更新迭代位置
            return &(map->table[i]); // 返回当前槽位的元素
        }
    }

    assert(map->used == 0 || i == max); // 确保所有元素都已遍历
    return NULL; // 如果没有更多元素,返回NULL
}

// 字典的打印函数,用于格式化输出字典内容
static void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
   
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); // 转换对象指针为字典结构体指针
    bool first = true; // 是否为第一个元素,用于控制输出格式
    const char *item_separator = ", "; // 元素分隔符
    const char *key_separator = ": "; // 键值分隔符

    // 根据打印类型(如JSON或普通字符串)调整分隔符
    if (!(MICROPY_PY_JSON && kind == PRINT_JSON)) {
   
        kind = PRINT_REPR;
    } else {
   
        #if MICROPY_PY_JSON_SEPARATORS
        item_separator = MP_PRINT_GET_EXT(print)->item_separator;
        key_separator = MP_PRINT_GET_EXT(print)->key_separator;
        #endif
    }

    // 如果是有序字典,打印类型名称
    if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) {
   
        mp_printf(print, "%q(", self->base.type->name);
    }
    mp_print_str(print, "{"); // 打印左大括号
    size_t cur = 0; // 初始化迭代位置
    mp_map_elem_t *next = NULL; // 当前迭代到的元素
    while ((next = dict_iter_next(self, &cur)) != NULL) {
    // 遍历字典
        if (!first) {
    // 如果不是第一个元素,打印分隔符
            mp_print_str(print, item_separator);
        }
        first = false; // 更新标志位

        // 根据是否为JSON打印格式,决定是否为键添加引号
        bool add_quote = MICROPY_PY_JSON && kind == PRINT_JSON && !mp_obj_is_str_or_bytes(next->key);
        if (add_quote) {
   
            mp_print_str(print, "\"");
        }
        mp_obj_print_helper(print, next->key, kind); // 打印键
        if (add_quote) {
   
            mp_print_str(print, "\"");
        }
        mp_print_str(print, key_separator); // 打印键值分隔符
        mp_obj_print_helper(print, next->value, kind); // 打印值
    }
    mp_print_str(print, "}");
    if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) {
   
        mp_print_str(print, ")");
    }
}

// 创建新字典的函数
mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
   
    mp_obj_t dict_out = mp_obj_new_dict(0); // 创建一个新字典对象
    mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out); // 转换对象指针为字典结构体指针
    dict->base.type = type; // 设置字典的基础类型

    // 如果是有序字典,设置相应的标志位
    #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
    if (type == &mp_type_ordereddict) {
   
        dict->map.is_ordered = 1;
    }
    #endif

    // 如果有参数传递,执行更新操作
    if (n_args > 0 || n_kw > 0) {
   
        mp_obj_t args2[2] = {
   dict_out, args[0]}; // 构造参数数组,args[0]是必须存在的
        mp_map_t kwargs; // 创建一个临时的参数映射
        mp_map_init_fixed_table(&kwargs, n_kw, args + n_args); // 初始化参数映射
        dict_update(n_args + 1, args2, &kwargs); // 调用更新函数,注意参数数量检查
    }
    return dict_out; // 返回新创建的字典对象
}

// 字典单目操作函数,处理如bool()和len()等操作
static mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
   
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); // 转换对象指针为字典结构体指针
    switch (op) {
   
        case MP_UNARY_OP_BOOL: // 判断字典是否为空
            return mp_obj_new_bool(self->map.used != 0);
        case MP_UNARY_OP_LEN: // 获取字典长度(元素数量)
            return MP_OBJ_NEW_SMALL_INT(self->map.used);
        #if MICROPY_PY_SYS_GETSIZEOF
        case MP_UNARY_OP_SIZEOF: // 获取字典对象占用的内存大小
            size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc;
            return MP_OBJ_NEW_SMALL_INT(sz);
        #endif
        default:
            return MP_OBJ_NULL; // 操作不支持
    }
}

// 字典二目操作函数,处理如in、==、|、or等操作
static mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
   
    mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in); // 转换左侧对象指针为字典结构体指针
    switch (op) {
   
        case MP_BINARY_OP_CONTAINS: // 判断字典是否包含某个键
            mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
            return mp_obj_new_bool(elem != NULL);
        case MP_BINARY_OP_EQUAL: // 判断两个字典是否相等
            // 如果是有序字典的情况,需要特殊处理
            #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
            if (MP_UNLIKELY(mp_obj_is_type(lhs_in, &mp_type_ordereddict) && mp_obj_is_type(rhs_in, &mp_type_ordereddict))) {
   
                // 同时遍历两个字典,比较键和值
                mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
                size_t c1 = 0, c2 = 0;
                mp_map_elem_t *e1 = dict_iter_next(o, &c1), *e2 = dict_iter_next(rhs, &c2);
                for (; e1 != NULL && e2 != NULL; e1 = dict_iter_next(o, &c1), e2 = dict_iter_next(rhs, &c2)) {
   
                    if (!mp_obj_equal(e1->key, e2->key) || !mp_obj_equal(e1->value, e2->value)) {
   
                        return mp_const_false;
                    }
                }
                return e1 == NULL && e2 == NULL ?mp_const_true : mp_const_false;
            }
            #endif

            // 如果右侧对象也是字典,比较它们的键值对
            if (mp_obj_is_type(rhs_in, &mp_type_dict)) {
   
                mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
                if (o->map.used != rhs->map.used) {
   
                    return mp_const_false;
                }

                size_t cur = 0;
                mp_map_elem_t *next = NULL;
                while ((next = dict_iter_next(o, &cur)) != NULL) {
   
                    mp_map_elem_t *elem = mp_map_lookup(&rhs->map, next->key, MP_MAP_LOOKUP);
                    if (elem == NULL || !mp_obj_equal(next->value, elem->value)) {
   
                        return mp_const_false;
                    }
                }
                return mp_const_true;
            } else {
   
                // 字典与其它类型的对象不相等
                return mp_const_false;
            }
        #if MICROPY_CPYTHON_COMPAT
        case MP_BINARY_OP_INPLACE_OR:
        case MP_BINARY_OP_OR: // 对字典进行合并操作
            if (op == MP_BINARY_OP_OR) {
   
                lhs_in = mp_obj_dict_copy(lhs_in); // 复制字典,以便后续修改
            }
            mp_obj_t dicts[2] = {
   lhs_in, rhs_in}; // 构造包含两个字典的数组
            dict_update(2, dicts, (mp_map_t *)&mp_const_empty_map); // 更新字典,合并内容
            return lhs_in; // 返回左侧字典对象
        }
        #endif
        default:
            // 操作不支持
            return MP_OBJ_NULL;
    }
}

// 字典项的获取函数,用于实现字典的索引操作
mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {
   
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); // 转换对象指针为字典结构体指针
    mp_map_elem_t *elem = mp_map_lookup(&self->map,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值