Cython中实现SlotsMeta元类遇问题,求解决方案
Cython元类SlotsMeta实现问题
我想在Cython里实现一个名为SlotsMeta的元类,目标是让使用这个元类的类,其所有类变量都变成Cython中的readonly属性。我的思路是把元类__cinit__方法传入的**kwargs里的类变量(作为键)转成Tuple[str],再赋值给SlotsMeta.__slots__。
参考了以下资料:
- Python Metaclass defining slots makes slots readonly
- sagelib的
classcall_metaclass.pxd实现 - sagelib的
classcall_metaclass.pyx实现
我的Cython实现代码如下:
#cython: language_level=3 # copied from sagelib的classcall_metaclass.pyx from cpython cimport PyObject, Py_XDECREF cdef extern from "Python.h": ctypedef PyObject *(*callfunc)(type, object, object) except NULL ctypedef struct PyTypeObject_call "PyTypeObject": callfunc tp_call # needed to call type.__call__ at very high speed. cdef PyTypeObject_call PyType_Type # Python's type cdef class SlotsMeta(type): cdef readonly tuple __slots__ def __init__(mcls, str name, tuple bases, dict attrs): attrs_keys = tuple(str(k) for k in attrs.keys()) mcls.__slots__ = attrs_keys def __call__(cls, *args, **kwargs): ptr = PyType_Type.tp_call(cls, args, kwargs) inst = <object>ptr inst.__init__(*args, **kwargs) Py_XDECREF(ptr) # During the cast to <object> Cython did INCREF(res) return inst
测试代码执行失败:
class A(metaclass=SlotsMeta): B: str = "H" def test_slotsmeta(): a = A() # passes assert a.B == "H" # passes with pytest.raises(AttributeError): # passes a.C # passes with pytest.raises(AttributeError): a.C = 500 # failed assert a.__slots__ == ("B", ) # failed
目前遇到的问题:
- 本应无法给实例
a添加属性C(a.C = 500),但实际可以执行成功 a.__slots__应该返回("B",),但实际没有返回预期值- 实例
a的__dict__本不应存在,但实际存在
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

