如何在Python类定义完成后自动处理ctypes.Structure类型提示?
如何自动在ctypes.Structure子类定义完成后处理类型提示字段?
我正在实现带有类型提示的ctypes.Structure类,当前代码如下:
import ctypes _CData = ctypes.c_int.__mro__[2] def set_fields_from_annotations(cls): from typing import get_type_hints if annotations := getattr(cls, '__annotations__', {}): cls._fields_ = [(n, t) for n, t in get_type_hints(type('', (), { '__annotations__': annotations, '__module__': cls.__module__ })).items() if not hasattr(cls, n) and issubclass(t, _CData)] class Node(ctypes.Structure): value: ctypes.c_uint key: ctypes.c_uint parent: 'ctypes.POINTER(Node)' child: 'ctypes.POINTER(Node)' set_fields_from_annotations(Node) print(Node.parent)
目前的问题是,必须在每个子类定义后手动调用set_fields_from_annotations,想知道有没有方法可以自动挂钩“子类定义完成后”的时机,避免手动调用。
已尝试的方案
我曾尝试使用__init_subclass__实现自动处理,但触发了NameError: name 'Node' is not defined.;当移除类型为'ctypes.POINTER(Node)'的自引用属性后,又出现了SystemError。
尝试的代码:
class StructureByAnnotations(ctypes.Structure): def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) set_fields_from_annotations(cls) class Node(StructureByAnnotations): value: ctypes.c_uint key: ctypes.c_uint # parent: 'ctypes.POINTER(Node)' # child: 'ctypes.POINTER(Node)'
报错信息:
Traceback (most recent call last): File "D:\Projects\pythonProject\main.py", line 21, in <module> class Node(StructureByAnnotations): File "D:\Projects\pythonProject\main.py", line 17, in __init_subclass__ set_fields_from_annotations(cls) File "D:\Projects\pythonProject\main.py", line 9, in set_fields_from_annotations cls._fields_ = [(n, t) for n, t in get_type_hints(type('', (), { SystemError: error return without exception set
2022-10-11更新:解决方案(感谢@SUTerliakov)
通过装饰器实现自动处理,同时解决了自引用类型的解析问题:
import ctypes import sys _CData = ctypes.c_int.__mro__[2] def set_fields_from_annotations(cls): from typing import get_type_hints global_namespace = getattr(sys.modules.get(cls.__module__, None), '__dict__', {}) global_namespace[cls.__name__] = cls if annotations := getattr(cls, '__annotations__', {}): # 原有逻辑保留,补充全局命名空间以支持自引用类型解析 cls._fields_ = [(n, t) for n, t in get_type_hints(type(cls.__name__, (), { '__annotations__': annotations, '__module__': cls.__module__ }), global_namespace).items() if not hasattr(cls, n) and issubclass(t, _CData)] return cls @set_fields_from_annotations class Node(ctypes.Structure): value: ctypes.c_uint key: ctypes.c_uint parent: 'ctypes.POINTER(Node)' child: 'ctypes.POINTER(Node)' print(Node.child)
内容的提问来源于stack exchange,提问作者nyao
相关产品推荐
相关产品推荐

