Langage de base

Generated Fri 19 Jun 2026 22:08:45 UTC

Classes

La méthode spéciale __del__ n’est pas implémentée pour les classes définies par l’utilisateur

Exemple de code

import gc


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


f = Foo()
del f

gc.collect()

CPython output:

MicroPython output:

__del__

__init_subclass__ isn’t automatically called.

Cause: MicroPython does not currently implement PEP 487.

Workaround: Manually call __init_subclass__ after class creation if needed. e.g.:

class A(Base):
    pass
A.__init_subclass__()

Exemple de code

class Base:
    @classmethod
    def __init_subclass__(cls):
        print(f"Base.__init_subclass__({cls.__name__})")


class A(Base):
    pass

CPython output:

MicroPython output:

Base.__init_subclass__(A)

__init_subclass__ isn’t an implicit classmethod.

Cause: MicroPython does not currently implement PEP 487. __init_subclass__ is not currently in the list of special-cased class/static methods.

Workaround: Decorate declarations of __init_subclass__ with @classmethod.

Exemple de code

def regularize_spelling(text, prefix="bound_"):
    # for regularizing across the CPython "method" vs MicroPython "bound_method" spelling for the type of a bound classmethod
    if text.startswith(prefix):
        return text[len(prefix) :]
    return text


class A:
    def __init_subclass__(cls):
        pass

    @classmethod
    def manual_decorated(cls):
        pass


a = type(A.__init_subclass__).__name__
b = type(A.manual_decorated).__name__

print(regularize_spelling(a))
print(regularize_spelling(b))
if a != b:
    print("FAIL")

CPython output:

MicroPython output:

method
method
function
method
FAIL

MicroPython doesn’t support parameterized __init_subclass__ class customization.

Cause: MicroPython does not currently implement PEP 487. The MicroPython syntax tree does not include a kwargs node after the class inheritance list.

Workaround: Use class variables or another mechanism to specify base-class customizations.

Exemple de code

class Base:
    @classmethod
    def __init_subclass__(cls, arg=None, **kwargs):
        cls.init_subclass_was_called = True
        print(f"Base.__init_subclass__({cls.__name__}, {arg=!r}, {kwargs=!r})")


class A(Base, arg="arg"):
    pass


# Regularize across MicroPython not automatically calling __init_subclass__ either.
if not getattr(A, "init_subclass_was_called", False):
    A.__init_subclass__()

CPython output:

MicroPython output:

Base.__init_subclass__(A, arg='arg', kwargs={})
Traceback (most recent call last):
  File "<stdin>", line 16, in <module>
TypeError: function doesn't take keyword arguments

__init_subclass__ can’t be defined a cooperatively-recursive way.

Cause: MicroPython does not currently implement PEP 487. The base object type does not have an __init_subclass__ implementation.

Workaround: Omit the recursive __init_subclass__ call unless it’s known that the grandparent also defines it.

Exemple de code

class Base:
    @classmethod
    def __init_subclass__(cls, **kwargs):
        cls.init_subclass_was_called = True
        super().__init_subclass__(**kwargs)


class A(Base):
    pass


# Regularize across MicroPython not automatically calling __init_subclass__ either.
if not getattr(A, "init_subclass_was_called", False):
    A.__init_subclass__()

CPython output:

MicroPython output:

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

L’ordre de résolution des méthodes (MRO) n’est pas conforme à CPython

Cause : Ordre de résolution des méthodes en profondeur d’abord, non exhaustif

Contournement : Évitez les hiérarchies de classes complexes avec héritage multiple et substitutions de méthodes complexes. Gardez à l’esprit que de nombreux langages ne supportent pas du tout l’héritage multiple.

Exemple de code

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


class C(tuple, Foo):
    pass


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

CPython output:

MicroPython output:

Foo
(1, 2, 3)

La modification de noms des membres privés de classe n’est pas implémentée

Cause : Le compilateur MicroPython n’implémente pas la modification de noms pour les membres privés de classe.

Contournement : Évitez les collisions avec les noms globaux en ajoutant manuellement un préfixe unique au nom du membre privé de classe.

Exemple de code

def __print_string(string):
    print(string)


class Foo:
    def __init__(self, string):
        self.string = string

    def do_print(self):
        __print_string(self.string)


example_string = "Example String to print."

class_item = Foo(example_string)
print(class_item.string)

class_item.do_print()

CPython output:

MicroPython output:

Example String to print.
Traceback (most recent call last):
  File "<stdin>", line 26, in <module>
  File "<stdin>", line 18, in do_print
NameError: name '_Foo__print_string' is not defined. Did you mean: '__print_string'?
Example String to print.
Example String to print.

Lors de l’héritage de types natifs, appeler une méthode dans __init__(self, ...) avant super().__init__() lève une AttributeError (ou provoque une erreur de segmentation si MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG n’est pas activé).

Cause : MicroPython ne possède pas de méthodes __new__ et __init__ séparées dans les types natifs.

Contournement : Appelez super().__init__() en premier.

Exemple de code

class L1(list):
    def __init__(self, a):
        self.append(a)


try:
    L1(1)
    print("OK")
except AttributeError:
    print("AttributeError")


class L2(list):
    def __init__(self, a):
        super().__init__()
        self.append(a)


try:
    L2(1)
    print("OK")
except AttributeError:
    print("AttributeError")

CPython output:

MicroPython output:

OK
OK
AttributeError
OK

Lors de l’héritage de plusieurs classes, super() n’appelle qu’une seule classe

Cause : Voir L’ordre de résolution des méthodes (MRO) n’est pas conforme à CPython

Contournement : Voir L’ordre de résolution des méthodes (MRO) n’est pas conforme à CPython

Exemple de code

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()

CPython output:

MicroPython output:

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

Appeler une propriété getter via super() dans une sous-classe retourne un objet property, et non la valeur

Exemple de code

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


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


a = AA()
print(a.p)

CPython output:

MicroPython output:

{'a': 10}
<property>

Exceptions

Throwing a derived exception class instance in its __init__ without first calling super().__init__ is a TypeError

Cause: In MicroPython, an object is incompletely constructed if it does not call its superclass init function or return normally from its __init__. This prevents its usage in some circumstances.

Workaround: Call the superclass __init__ method before raising the exception.

Exemple de code

class C(Exception):
    def __init__(self):
        raise self


class C1(Exception):
    def __init__(self):
        super().__init__()
        raise self


try:
    C()
except Exception as e:
    print(type(e).__name__)

try:
    C1()
except Exception as e:
    print(type(e).__name__)

CPython output:

MicroPython output:

C
C1
TypeError
C1

Fonctions

Les messages d’erreur pour les méthodes peuvent afficher des nombres d’arguments inattendus

Cause : MicroPython compte « self » comme un argument.

Contournement : Interprétez les messages d’erreur en tenant compte de cette information.

Exemple de code

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

CPython output:

MicroPython output:

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

Les objets fonction ne possèdent pas l’attribut __module__

Cause : MicroPython est optimisé pour réduire la taille du code et l’utilisation de la RAM.

Contournement : Utilisez sys.modules[function.__globals__['__name__']] pour les modules non intégrés.

Exemple de code

def f():
    pass


print(f.__module__)

CPython output:

MicroPython output:

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

Les attributs définis par l’utilisateur pour les fonctions ne sont pas pris en charge

Cause : MicroPython est fortement optimisé pour l’utilisation de la mémoire.

Contournement : Utilisez un dictionnaire externe, par ex. FUNC_X[f] = 0.

Exemple de code

def f():
    pass


f.x = 0
print(f.x)

CPython output:

MicroPython output:

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

Générateur

Le gestionnaire de contexte __exit__() n’est pas appelé dans un générateur qui ne s’exécute pas jusqu’à la fin

Exemple de code

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()

CPython output:

MicroPython output:

Enter
1
2
3
Exit
Enter
1
2
3

Environnement d’exécution

Les variables locales ne sont pas incluses dans le résultat de locals()

Cause : MicroPython ne maintient pas un environnement local symbolique ; il est optimisé sous forme d’un tableau de cases. Ainsi, les variables locales ne sont pas accessibles par nom.

Exemple de code

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


test()

CPython output:

MicroPython output:

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

Le code exécuté dans la fonction eval() n’a pas accès aux variables locales

Cause : MicroPython ne maintient pas un environnement local symbolique ; il est optimisé sous forme d’un tableau de cases. Ainsi, les variables locales ne sont pas accessibles par nom. En pratique, eval(expr) dans MicroPython est équivalent à eval(expr, globals(), globals()).

Exemple de code

val = 1


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


test()

CPython output:

MicroPython output:

2
2
2
1

f-strings

Les f-strings ne supportent pas la concaténation avec des littéraux adjacents si ceux-ci contiennent des accolades

Cause : MicroPython est optimisé pour l’espace de code.

Contournement : Utilisez l’opérateur + entre les chaînes littérales lorsqu’elles ne sont pas toutes les deux des f-strings

Exemple de code

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

CPython output:

MicroPython output:

aa1
1ab
a{}a1
1a{}b
aa1
1ab
Traceback (most recent call last):
  File "<stdin>", line 12, in <module>
IndexError: tuple index out of range

Les f-strings ne peuvent pas supporter les expressions nécessitant une analyse syntaxique pour résoudre des accolades et crochets imbriqués non équilibrés

Cause : MicroPython est optimisé pour l’espace de code.

Contournement : Utilisez toujours des accolades et crochets équilibrés dans les expressions à l’intérieur des f-strings

Exemple de code

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

CPython output:

MicroPython output:

hello { world
hello ] world
Traceback (most recent call last):
  File "<stdin>", line 9
SyntaxError: invalid syntax

Les f-strings ne supportent pas les conversions !a

Cause : MicroPython n’implémente pas ascii()

Contournement : Aucun

Exemple de code

f"{'unicode text'!a}"

CPython output:

MicroPython output:

Traceback (most recent call last):
  File "<stdin>", line 8
SyntaxError: invalid syntax

import

L’attribut __path__ d’un paquet est d’un type différent (chaîne unique au lieu d’une liste de chaînes) dans MicroPython

Cause : MicroPython ne prend pas en charge les paquets d’espaces de noms répartis sur le système de fichiers. De plus, le système d’importation de MicroPython est fortement optimisé pour une utilisation minimale de la mémoire.

Contournement : Les détails de la gestion des importations dépendent intrinsèquement de l’implémentation. Ne vous fiez pas à ces détails dans des applications portables.

Exemple de code

import modules

print(modules.__path__)

CPython output:

MicroPython output:

['/home/runner/work/openmv-doc/openmv-doc/micropython/tests/cpydiff/modules']
../tests/cpydiff/modules

MicroPython ne prend pas en charge les paquets d’espaces de noms répartis sur le système de fichiers.

Cause : Le système d’importation de MicroPython est fortement optimisé pour la simplicité, une utilisation minimale de la mémoire et un overhead minimal lors des recherches dans le système de fichiers.

Contournement : N’installez pas dans des répertoires différents des modules appartenant au même paquet d’espace de noms. Pour MicroPython, il est recommandé d’avoir au maximum 3 composantes dans les chemins de recherche de modules : pour votre application courante, par utilisateur (accessible en écriture) et à l’échelle du système (non accessible en écriture).

Exemple de code

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")

CPython output:

MicroPython output:

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