核心语言

Generated Wed 14 Aug 2024 09:10:45 UTC

f-strings 不支持与相邻文字的拼接,如果相邻文字包含大括号或是 f-strings

原因: MicroPython 优化了代码空间。

解决方法: 当其中一个或两者都是 f-strings 时,使用 + 操作符连接文字字符串

示例代码:

x, y = 1, 2
print("aa" f"{x}")  # works
print(f"{x}" "ab")  # works
print("a{}a" f"{x}")  # fails
print(f"{x}" "a{}b")  # fails
print(f"{x}" f"{y}")  # fails

CPy输出:

uPy输出:

aa1
1ab
a{}a1
1a{}b
12
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

f-strings 无法支持需要解析来解决不平衡嵌套大括号和方括号的表达式

原因: MicroPython 优化了代码空间。

解决方法: 在 f-strings 内的表达式中始终使用平衡的大括号和方括号

示例代码:

print(f'{"hello { world"}')
print(f'{"hello ] world"}')

CPy输出:

uPy输出:

hello { world
hello ] world
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

不支持原始 f-strings

原因: MicroPython 优化了代码空间。

示例代码:

rf"hello"

CPy输出:

uPy输出:

/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

f-strings don’t support !a conversions

Cause: MicropPython does not implement ascii()

Workaround: None

示例代码:

f"{'unicode text'!a}"

CPy输出:

uPy输出:

/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

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

示例代码:

import gc


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


f = Foo()
del f

gc.collect()

CPy输出:

uPy输出:

__del__
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

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

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

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

示例代码:

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


class C(tuple, Foo):
    pass


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

CPy输出:

uPy输出:

Foo
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

从多个类继承时,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__
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

在子类中调用 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}
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

函数

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

原因: MicroPython 将 “self” 作为参数计算。

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

示例代码:

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

CPy输出:

uPy输出:

list.append() takes exactly one argument (0 given)
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

函数对象没有 __module__ 属性

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

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

示例代码:

def f():
    pass


print(f.__module__)

CPy输出:

uPy输出:

__main__
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

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

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

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

示例代码:

def f():
    pass


f.x = 0
print(f.x)

CPy输出:

uPy输出:

0
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

生成器

在不完全运行的生成器中,上下文管理器 __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
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

运行时

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

原因: MicroPython 不维护符号局部环境,它被优化为一个插槽数组。因此,局部变量不能通过名称访问。

示例代码:

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


test()

CPy输出:

uPy输出:

{'val': 2}
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

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

原因: MicroPython 不维护符号局部环境,它被优化为一个插槽数组。因此,局部变量不能通过名称访问。从效果上讲,MicroPython 中的 eval(expr) 相当于 eval(expr, globals(), globals())

示例代码:

val = 1


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


test()

CPy输出:

uPy输出:

2
2
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

导入

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

原因: 未实现。

解决方法: 直接在 __init__.py 中使用 from . import foo, bar 手动导入子模块。

示例代码:

from modules3 import *

foo.hello()

CPy输出:

uPy输出:

hello
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

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

Cause: MicroPython doesn’t support namespace packages split across filesystem. Beyond that, MicroPython’s import system is highly optimized for minimal memory usage.

解决方法: 导入处理的详细信息在本质上是与实现相关的。在可移植应用程序中不要依赖此类详细信息。

示例代码:

import modules

print(modules.__path__)

CPy输出:

uPy输出:

['/builds/openmv/openmv-doc/micropython/tests/cpydiff/modules']
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found

MicroPython doesn’t support namespace packages split across filesystem.

原因: 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
/bin/sh: 1: ../ports/unix/build-standard/micropython: not found