You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:40:25