核心语言

2021 年 7 月 9 日星期五 00:08:56 UTC 生成

班级

未为用户定义的类实现特殊方法 __del__

示例代码:

import gc


class Foo:
    def __del__(self):
        print("__del__")


f = Foo()
del f

gc.collect()

CPy 输出:

uPy 输出:

__del__

方法解析顺序 (MRO) 不符合 CPython

原因: 深度优先非穷尽方法解析顺序

解决方法: 避免具有多重继承和复杂方法覆盖的复杂类层次结构。请记住,许多语言根本不支持多重继承。

示例代码:

class Foo:
    def __str__(self):
        return "Foo"


class C(tuple, Foo):
    pass


t = C((1, 2, 3))
print(t)

CPy 输出:

uPy 输出:

Foo
(1, 2, 3)

从多个类继承时 super() 只调用一个类

原因: 请参阅 方法解析顺序 (MRO) 不符合 CPython

解决方法请参阅方法解析顺序 (MRO) 与 CPython 不兼容

示例代码:

class A:
    def __init__(self):
        print("A.__init__")


class B(A):
    def __init__(self):
        print("B.__init__")
        super().__init__()


class C(A):
    def __init__(self):
        print("C.__init__")
        super().__init__()


class D(B, C):
    def __init__(self):
        print("D.__init__")
        super().__init__()


D()

CPy 输出:

uPy 输出:

D.__init__
B.__init__
C.__init__
A.__init__
D.__init__
B.__init__
A.__init__

在子类中调用 super() getter 属性将返回一个属性对象,而不是值

示例代码:

class A:
    @property
    def p(self):
        return {"a": 10}


class AA(A):
    @property
    def p(self):
        return super().p


a = AA()
print(a.p)

CPy 输出:

uPy 输出:

{'a': 10}
<property>

职能

方法的错误消息可能会显示意外的参数计数

原因:MicroPython 将“自我”视为参数。

解决方法: 根据上述信息解释错误消息。

示例代码:

try:
    [].append()
except Exception as e:
    print(e)

CPy 输出:

uPy 输出:

append() takes exactly one argument (0 given)
function takes 2 positional arguments but 1 were given

函数对象没有__module__ 属性

原因:MicroPython 针对减少代码大小和 RAM 使用进行了优化。

解决方法: 使用 sys.modules[function.__globals__['__name__']] 非内置模块。

示例代码:

def f():
    pass


print(f.__module__)

CPy 输出:

uPy 输出:

__main__
Traceback (most recent call last):
  File "<stdin>", line 13, in <module>
AttributeError: 'function' object has no attribute '__module__'

不支持函数的用户定义属性

原因: MicroPython 针对内存使用进行了高度优化。

解决方法: 使用外部字典,例如.FUNC_X[f] = 0.

示例代码:

def f():
    pass


f.x = 0
print(f.x)

CPy 输出:

uPy 输出:

0
Traceback (most recent call last):
  File "<stdin>", line 13, in <module>
AttributeError: 'function' object has no attribute 'x'

发电机

上下文管理器 __exit__() 未在未运行完成的生成器中调用

示例代码:

class foo(object):
    def __enter__(self):
        print("Enter")

    def __exit__(self, *args):
        print("Exit")


def bar(x):
    with foo():
        while True:
            x += 1
            yield x


def func():
    g = bar(0)
    for _ in range(3):
        print(next(g))


func()

CPy 输出:

uPy 输出:

Enter
1
2
3
Exit
Enter
1
2
3

运行

locals() 结果中不包含局部变量

原因: MicroPython 不维护符号本地环境,它针对插槽数组进行了优化。因此,不能通过名称访问局部变量。

示例代码:

def test():
    val = 2
    print(locals())


test()

CPy 输出:

uPy 输出:

{'val': 2}
{'test': <function test at 0x7fd179e25100>, '__name__': '__main__', '__file__': '<stdin>'}

在 eval() 函数中运行的代码无权访问局部变量

原因: MicroPython 不维护符号本地环境,它针对插槽数组进行了优化。因此,不能通过名称访问局部变量。实际上,eval(expr)在 MicroPython 中相当于. eval(expr, globals(), globals())

示例代码:

val = 1


def test():
    val = 2
    print(val)
    eval("print(val)")


test()

CPy 输出:

uPy 输出:

2
2
2
1

进口

__all__ 在 MicroPython 的 __init__.py 中不受支持。

原因: 未实施。

解决方法:在 __init__.py 中使用.from . import foo, bar

示例代码:

from modules3 import *

foo.hello()

CPy 输出:

uPy 输出:

hello
Traceback (most recent call last):
  File "<stdin>", line 9, in <module>
NameError: name 'foo' isn't defined

包的 __path__ 属性在 MicroPython 中具有不同的类型(单个字符串而不是字符串列表)

原因: MicroPython 不支持跨文件系统拆分的命名空间包。除此之外,MicroPython 的导入系统针对最小内存使用量进行了高度优化。

解决方法: 导入处理的详细信息本质上取决于实现。不要依赖便携式应用程序中的这些细节。

示例代码:

import modules

print(modules.__path__)

CPy 输出:

uPy 输出:

['/home/micropython/micropython-docs/tests/cpydiff/modules']
../tests/cpydiff//modules

未能加载模块仍注册为已加载

原因: 为了使模块处理更有效,它没有用异常处理包装。

解决方法: 在生产使用前测试模块;在开发、使用或只是软或硬重置电路板。del sys.modules["name"]

示例代码:

import sys

try:
    from modules import foo
except NameError as e:
    print(e)
try:
    from modules import foo

    print("Should not get here")
except NameError as e:
    print(e)

CPy 输出:

uPy 输出:

foo
name 'xxx' is not defined
foo
name 'xxx' is not defined
foo
name 'xxx' isn't defined
Should not get here

MicroPython 不支持跨文件系统拆分的命名空间包。

原因: MicroPython 的导入系统针对简单性、最小内存使用量和最小文件系统搜索开销进行了高度优化。

解决方法:不要在不同目录中安装属于同一命名空间包的模块。对于 MicroPython,建议最多具有 3 个组件模块搜索路径:对于您当前的应用程序、每个用户(可写)、系统范围(不可写)。

示例代码:

import sys

sys.path.append(sys.path[1] + "/modules")
sys.path.append(sys.path[1] + "/modules2")

import subpkg.foo
import subpkg.bar

print("Two modules of a split namespace package imported")

CPy 输出:

uPy 输出:

Two modules of a split namespace package imported
Traceback (most recent call last):
  File "<stdin>", line 13, in <module>
ImportError: no module named 'subpkg.bar'