【发布时间】:2022-11-19 11:34:13
【问题描述】:
我正在努力实现一个带有类型提示的 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__', {}):
# It's what you were already doing
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)
【问题讨论】:
-
您最好将您的解决方案作为答案发布 - 自我回答问题很好:)
标签: python python-3.x python-typing