Ngôn ngữ cốt lõi¶
Generated Thu 18 Jun 2026 14:23:40 UTC
Lớp (Classes)¶
Phương thức đặc biệt __del__ chưa được triển khai cho các lớp do người dùng định nghĩa¶
Mã ví dụ:
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__()
Mã ví dụ:
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.
Mã ví dụ:
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.
Mã ví dụ:
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.
Mã ví dụ:
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__'
|
Thứ tự phân giải phương thức (MRO) không tuân thủ CPython¶
Nguyên nhân: Thứ tự phân giải phương thức theo chiều sâu không đầy đủ
Cách khắc phục: Tránh các hệ thống phân cấp lớp phức tạp với đa kế thừa và ghi đè phương thức phức tạp. Hãy nhớ rằng nhiều ngôn ngữ không hỗ trợ đa kế thừa.
Mã ví dụ:
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)
|
Xáo trộn tên thành viên lớp riêng tư (Private Class Members name mangling) chưa được triển khai¶
Nguyên nhân: Trình biên dịch MicroPython không triển khai xáo trộn tên cho các thành viên lớp riêng tư.
Cách khắc phục: Tránh sử dụng hoặc xung đột với tên toàn cục, bằng cách thêm tiền tố duy nhất vào tên thành viên lớp riêng tư theo cách thủ công.
Mã ví dụ:
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.
|
Khi kế thừa các kiểu native, gọi một phương thức trong __init__(self, ...) trước super().__init__() sẽ gây ra AttributeError (hoặc segfault nếu MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG không được bật).¶
Nguyên nhân: MicroPython không có các phương thức __new__ và __init__ riêng biệt trong các kiểu native.
Cách khắc phục: Gọi super().__init__() trước.
Mã ví dụ:
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
|
Khi kế thừa từ nhiều lớp, super() chỉ gọi một lớp¶
Nguyên nhân: Xem Thứ tự phân giải phương thức (MRO) không tuân thủ CPython
Cách khắc phục: Xem Thứ tự phân giải phương thức (MRO) không tuân thủ CPython
Mã ví dụ:
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__
|
Gọi thuộc tính getter super() trong lớp con sẽ trả về đối tượng property, không phải giá trị¶
Mã ví dụ:
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.
Mã ví dụ:
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
|
Hàm (Functions)¶
Thông báo lỗi cho các phương thức có thể hiển thị số đối số không mong đợi¶
Nguyên nhân: MicroPython tính "self" là một đối số.
Cách khắc phục: Giải thích các thông báo lỗi với thông tin trên trong đầu.
Mã ví dụ:
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
|
Đối tượng Function không có thuộc tính __module__¶
Nguyên nhân: MicroPython được tối ưu hóa để giảm kích thước mã và sử dụng RAM.
Cách khắc phục: Sử dụng sys.modules[function.__globals__['__name__']] cho các module không tích hợp.
Mã ví dụ:
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__'
|
Không hỗ trợ thuộc tính do người dùng định nghĩa cho hàm¶
Nguyên nhân: MicroPython được tối ưu hóa cao cho việc sử dụng bộ nhớ.
Cách khắc phục: Sử dụng từ điển ngoài, ví dụ: FUNC_X[f] = 0.
Mã ví dụ:
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'
|
Generator¶
Context manager __exit__() không được gọi trong generator không chạy đến khi hoàn thành¶
Mã ví dụ:
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
|
Runtime¶
Biến cục bộ không được bao gồm trong kết quả locals()¶
Nguyên nhân: MicroPython không duy trì môi trường cục bộ mang tính ký hiệu, nó được tối ưu hóa thành mảng các slot. Do đó, các biến cục bộ không thể được truy cập bằng tên.
Mã ví dụ:
def test():
val = 2
print(locals())
test()
CPython output: |
MicroPython output: |
{'val': 2}
|
{'test': <function test at 0x7f0526805260>, '__name__': '__main__', '__file__': '<stdin>'}
|
Mã chạy trong hàm eval() không có quyền truy cập vào các biến cục bộ¶
Nguyên nhân: MicroPython không duy trì môi trường cục bộ mang tính ký hiệu, nó được tối ưu hóa thành mảng các slot. Do đó, các biến cục bộ không thể được truy cập bằng tên. Về mặt thực tế, eval(expr) trong MicroPython tương đương với eval(expr, globals(), globals()).
Mã ví dụ:
val = 1
def test():
val = 2
print(val)
eval("print(val)")
test()
CPython output: |
MicroPython output: |
2
2
|
2
1
|
f-strings¶
f-string không hỗ trợ nối chuỗi với các chuỗi chữ liền kề nếu các chuỗi đó chứa dấu ngoặc nhọn¶
Nguyên nhân: MicroPython được tối ưu hóa cho kích thước mã.
Cách khắc phục: Sử dụng toán tử + giữa các chuỗi chữ khi chúng không đều là f-string
Mã ví dụ:
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
|
f-string không thể hỗ trợ các biểu thức yêu cầu phân tích cú pháp để giải quyết dấu ngoặc nhọn và ngoặc vuông lồng nhau không cân bằng¶
Nguyên nhân: MicroPython được tối ưu hóa cho kích thước mã.
Cách khắc phục: Luôn sử dụng dấu ngoặc nhọn và ngoặc vuông cân bằng trong các biểu thức bên trong f-string
Mã ví dụ:
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
|
f-string không hỗ trợ chuyển đổi !a¶
Nguyên nhân: MicroPython không triển khai ascii()
Cách khắc phục: Không có
Mã ví dụ:
f"{'unicode text'!a}"
CPython output: |
MicroPython output: |
Traceback (most recent call last):
File "<stdin>", line 8
SyntaxError: invalid syntax
|
import¶
Thuộc tính __path__ của một gói có kiểu khác (chuỗi đơn thay vì danh sách chuỗi) trong MicroPython¶
Nguyên nhân: MicroPython không hỗ trợ các gói namespace được phân tách trên hệ thống tệp. Ngoài ra, hệ thống import của MicroPython được tối ưu hóa cao cho việc sử dụng bộ nhớ tối thiểu.
Cách khắc phục: Chi tiết xử lý import về bản chất phụ thuộc vào triển khai. Đừng dựa vào các chi tiết như vậy trong các ứng dụng di động.
Mã ví dụ:
import modules
print(modules.__path__)
CPython output: |
MicroPython output: |
['/home/runner/work/openmv-doc/openmv-doc/micropython/tests/cpydiff/modules']
|
../tests/cpydiff/modules
|
MicroPython không hỗ trợ các gói namespace được phân tách trên hệ thống tệp.¶
Nguyên nhân: Hệ thống import của MicroPython được tối ưu hóa cao cho sự đơn giản, sử dụng bộ nhớ tối thiểu và chi phí tìm kiếm hệ thống tệp tối thiểu.
Cách khắc phục: Đừng cài đặt các module thuộc cùng một gói namespace vào các thư mục khác nhau. Đối với MicroPython, nên có tối đa 3 thành phần đường dẫn tìm kiếm module: cho ứng dụng hiện tại, mỗi người dùng (có thể ghi), toàn hệ thống (không thể ghi).
Mã ví dụ:
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'
|