MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
python编程示例系列 python编程示例系列二
python的Web神器Streamlit
这段代码是MicroPython的实现,主要功能是提供Python编程语言的核心功能和对象模型。具体来说,它包括以下几个方面:
对象和类型管理:代码中定义了如何创建和管理对象类型(mp_obj_type_t),包括类的创建、实例化、以及类的属性和方法的存储与访问。
实例创建:通过mp_obj_new_instance函数,可以创建一个新的对象实例,包括初始化其属性和方法。
属性和方法访问:提供了mp_obj_class_lookup、mp_obj_instance_load_attr、mp_obj_instance_store_attr等函数,用于在对象实例中查找、读取和设置属性。
特殊方法支持:实现了Python中的特殊方法,如__new__、init、str、repr、__call__等,这些方法对应于对象的创建、字符串表示、调用等行为。
操作符重载:通过instance_unary_op和instance_binary_op函数,实现了对一元和二元操作符的重载,允许自定义对象支持各种算术和比较操作。
迭代器和序列化:提供了mp_obj_instance_getiter和instance_subscr函数,支持迭代器协议和序列化访问,如列表索引和切片操作。
类型检查和继承:实现了mp_obj_is_subclass和mp_obj_is_instance函数,用于检查对象的类型和继承关系。
静态方法和类方法:通过mp_type_staticmethod和mp_type_classmethod,支持静态方法和类方法的定义和调用。
错误处理:在执行过程中,如果遇到不支持的操作或属性访问错误,会抛出相应的异常。
整体而言,这段代码是MicroPython虚拟机的一部分,负责实现Python语言的核心特性,使得在资源受限的微控制器上也能运行Python代码。
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
// 打印调试信息
#if MICROPY_DEBUG_VERBOSE
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else
#define DEBUG_PRINT (0)
#define DEBUG_printf(...) (void)0
#endif
// 启用特殊的访问器
#define ENABLE_SPECIAL_ACCESSORS (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY)
// 原生类型基类的实例计数
static int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
int count = 0;
for (;;) {
if (type == &mp_type_object) {
// 不是一个“真实”的类型,在这里结束搜索。
return count;
} else if (mp_obj_is_native_type(type)) {
// 原生类型没有父类(至少从我们的角度来看是这样),所以结束。
*last_native_base = type;
return count + 1;
#if MICROPY_MULTIPLE_INHERITANCE
} else if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) {
// 没有父类,所以在这里结束搜索。
return count;
} else {
// 单个父类,使用迭代继续搜索。
type = MP_OBJ_TYPE_GET_SLOT(type, parent);
}
#if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) {
// 多个父类,递归搜索它们所有。
const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent);
const mp_obj_t *item = parent_tuple->items;
const mp_obj_t *top = item + parent_tuple->len;
for (; item < top; ++item) {
assert(mp_obj_is_type(*item, &mp_type_type));
const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
count += instance_count_native_bases(bt, last_native_base);
}
return count;
}
#endif
}
}
// 这个包装函数允许从原生类型派生的子类调用原生类型的
// __init__() 方法(对应于 type->make_new)。
static mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) {
mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]);
const mp_obj_type_t *native_base = NULL;
instance_count_native_bases(self->base.type, &native_base);
self->subobj[0] = MP_OBJ_TYPE_GET_SLOT(native_base, make_new)(native_base, n_args - 1, 0, args + 1);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper);
#if !MICROPY_CPYTHON_COMPAT
static
#endif
mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) {
size_t num_native_bases = instance_count_native_bases(class, native_base);
assert(num_native_bases < 2);
mp_obj_instance_t *o = mp_obj_malloc_var(mp_obj_instance_t, subobj, mp_obj_t, num_native_bases, class);
mp_map_init(&o->members, 0);
// 初始化原生基类槽(如果有的话),使用一个有效的对象。
// 这个对象是什么并不重要,只要它能被唯一地识别为不是
// 一个被初始化的原生类。
if (num_native_bases != 0) {
o->subobj[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj);
}
return o;
}
// TODO
// 这实现了深度优先左到右的 MRO,这与 Python3 MRO 不兼容
// http://python-history.blogspot.com/2010/06/method-resolution-order.html
// https://www.python.org/download/releases/2.3/mro/
// 将保持 lookup->dest[0] 的值(如果未找到属性,应该是 MP_OBJ_NULL)。如果在一个
// 原生类型基类中通过槽 ID 找到了特殊方法(如 lookup->slot_offset 指定的),将设置为 MP_OBJ_SENTINEL。
// 由于只能有一个原生基类,所以我们知道它适用于 instance->subobj[0]。在大多数情况下,我们也不需要知道
// 是哪个类型 - 因为 instance->subobj[0] 是那种类型的对象。
// 唯一的例外是当对象尚未构造时,我们需要知道基原生类型,以便从该类型构造其 instance->subobj[0]。
// 但是这种情况通过 instance_count_native_bases() 处理,它返回它看到的原生基类。
// 这个函数还处理了从 instance->subobj[0] 调用原生构造函数的情况,这在 CPython 中是不允许的。
struct class_lookup_data {
mp_obj_instance_t *obj;
qstr attr;
size_t slot_offset;
mp_obj_t *dest;
bool is_type;
};
// 用于调试的打印
static void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) {
assert(lookup->dest[0] == MP_OBJ_NULL);
assert(lookup->dest[1] == MP_OBJ_NULL);
for (;;) {
DEBUG_printf("mp_obj_class_lookup: 在 %s 中查找 %s\n", qstr_str(lookup->attr), qstr_str(type->name));
// 优化原生类型的特殊方法查找
if (lookup->slot_offset != 0 && mp_obj_is_native_type(type)) {
// 检查指定的槽索引是否有非零值,
// 对于 getiter,槽不会设置,因为 MP_TYPE_FLAG_ITER_IS_STREAM。
if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset) || (lookup->slot_offset == MP_OBJ_TYPE_OFFSETOF_SLOT(iter) && type->flags & MP_TYPE_FLAG_ITER_IS_STREAM)) {
DEBUG_printf("mp_obj_class_lookup: 匹配特殊方法槽(off=%d)为 %s\n",
lookup->slot_offset, qstr_str(lookup->attr));
lookup->dest[0] = MP_OBJ_SENTINEL;
return;
}
}
if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) {
// 在 locals_dict(方法/属性集)中搜索
assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)))); // MicroPython 限制,目前是这样
mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map;
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP);
if (elem != NULL) {
if (lookup->is_type) {
// 如果我们查找一个类方法,我们需要返回原始类型,而不是我们找到类方法的(基)类型。
const mp_obj_type_t *org_type = (const mp_obj_type_t *)lookup->obj;
mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest);
} else {
mp_obj_instance_t *obj = lookup->obj;
mp_obj_t obj_obj;
if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object 不是一个真实的类型 */) {
// 如果我们处理的是原生基类,那么它适用于原生子对象
obj_obj = obj->subobj[0];
} else {
obj_obj = MP_OBJ_FROM_PTR(obj);
}
mp_obj_instance_t *self = lookup->obj;
mp_obj_t self_in = MP_OBJ_FROM_PTR(self);
mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest);
}
#if DEBUG_PRINT
DEBUG_printf("mp_obj_class_lookup: 返回: ");
mp_obj_print_helper(MICROPY_DEBUG_PRINTER, lookup->dest[0], PRINT_REPR);
if (lookup->dest[1] != MP_OBJ_NULL) {
// 尽量不要对 lookup->dest[1] 进行 repr(),因为我们可能会递归调用
DEBUG_printf(" <%s @%p>", mp_obj_get_type_str(lookup->dest[1]), MP_OBJ_TO_PTR(lookup->dest[1]));
}
DEBUG_printf("\n");
#endif
return;
}
}
// 之前的代码块处理了 .locals_dict 中定义的属性,
// 但是一些原生类型的属性可能使用 .load_attr 方法处理,
// 所以确保我们也尝试查找这些属性。
if (lookup->obj != NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object 不是一个真实的类型 */) {
mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest);
if(lookup->dest[0] != MP_OBJ_NULL) {
return;
}
}
// 属性未找到,继续搜索基类
if (!MP_OBJ_TYPE_HAS_SLOT(type, parent)) {
DEBUG_printf("mp_obj_class_lookup: 没有更多的父类\n");
return;
#if MICROPY_MULTIPLE_INHERITANCE
} else if (((mp_obj_base_t *)MP_OBJ_TYPE_GET_SLOT(type, parent))->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = MP_OBJ_TYPE_GET_SLOT(type, parent);
const mp_obj_t *item = parent_tuple->items;
const mp_obj_t *top = item + parent_tuple->len - 1;
for (; item < top; ++item) {
assert(mp_obj_is_type(*item, &mp_type_type));
mp_obj_type_t *bt = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
if (bt == &mp_type_object) {
// 不是一个“真实”的类型
continue;
}
mp_obj_class_lookup(lookup, bt);
if (lookup->dest[0] != MP_OBJ_NULL) {
return;
}
}
// 搜索最后一个基类(简单的尾递归消除)
assert(mp_obj_is_type(*item, &mp_type_type));
type = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
#endif
} else {
type = MP_OBJ_TYPE_GET_SLOT(type, parent);
}
if (type == &mp_type_object) {
// 不是一个“真实”的类型
return;
}
}
// 实例打印
static void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
mp_obj_t member[2] = {
MP_OBJ_NULL};
struct class_lookup_data lookup = {
.obj = self,
.attr = meth,
.slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(print),
.dest = member,
.is_type = false,
};
mp_obj_class_lookup(&lookup, self->base.type);
if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {
// 如果没有 __str__,回退到 __repr__
lookup.attr = MP_QSTR___repr__;
lookup.slot_offset = 0;
mp_obj_class_lookup(&lookup, self->base.type);
}
if (member[0] == MP_OBJ_SENTINEL) {
// 特殊处理 Exception 子类
if (mp_obj_is_native_exception_instance(self->subobj[0])) {
if (kind != PRINT_STR) {
mp_print_str(print, qstr_str(self->base.type->name));
}
mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
} else {
mp_obj_print_helper(print, self->subobj[0], kind);
}
return;
}
if (member[0] != MP_OBJ_NULL) {
mp_obj_t r = mp_call_function_1(member[0], self_in);
mp_obj_print_helper(print, r, PRINT_STR);
return;
}
// TODO: CPython 打印完全合格的类型名称
mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self);
}
// 实例创建新的实例
static mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
assert(mp_obj_is_instance_type(self));
// 查找 __new__ 函数
mp_obj_t init_fn[2] = {
MP_OBJ_NULL};
struct class_lookup_data lookup = {
.obj = NULL,
.attr = MP_QSTR___new__,
.slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(make_new),
.dest = init_fn,
.is_type = false,
};
mp_obj_class_lookup(&lookup, self);
const mp_obj_type_t *native_base = NULL;
mp_obj_instance_t *o;
if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) {
// 要么没有定义 __new__() 方法,要么有一个原生构造函数。
// 在这两种情况下,创建一个空白实例。
o = mp_obj_new_instance(self, &native_base);
// 由于 type->make_new() 实现了 __new__() 和 __init__(),
// 其中后者可能被 Python 子类覆盖,
// 我们推迟调用原生构造函数(见本函数末尾),
// 以便给 Python __init__() 方法一个机会来调用
// 所述原生构造函数。
} else {
// 调用 Python 类的 __new__ 函数,用所有参数创建一个实例
mp_obj_t new_ret;
if (n_args == 0 && n_kw == 0) {
mp_obj_t args2[1] = {
MP_OBJ_FROM_PTR(self)};
new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2);
} else {
mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw);
args2[0] = MP_OBJ_FROM_PTR(self);
memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2);
m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
}
// 根据 Python 3.4 参考数据模型 - object.__new__
// "如果 __new__() 返回的不是 cls 的实例,则不会调用新实例的 __init__() 方法。"
if (mp_obj_get_type(new_ret) != self) {
return new_ret;
}
// __new__() 返回的实例成为新对象
o = MP_OBJ_TO_PTR(new_ret);
}
// 现在调用 Python 类的 __init__ 函数,用所有参数
// 这个方法有机会调用 super().__init__() 来构造可能的原生基类。
init_fn[0] = init_fn